当前位置: 首页 > news >正文

操作系统之shell实现(上)

🌟 各位看官好,我是maomi_9526

🌍 种一棵树最好是十年前,其次是现在!

🚀 今天来学习C语言的相关知识。

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

目录

1. 进程创建

1.1fork函数

​编辑

1.2写时拷贝(Copy-on-write)

1.3 虚拟地址存储 

2. 进程终止

2.1进程退出情况

2.2退出方式

2.3退出码

2.4exit函数VS_exit函数

2.4.1exit函数

 2.4.2_exit函数

​编辑 2.4.3eixt VS_exit​编辑

3. 进程等待

3.1进程等待的必要性

 3.2wait等待

3.3获取子进程status 

4.总结

1. 进程创建

1.1fork函数

fork() 是 Linux 中非常重要的函数,用来从父进程创建一个子进程。父进程返回子进程的PID,子进程返回0。通过 fork() 创建的父子进程可以独立执行各自的代码。

头文件:#include<unistd.h>

返回值:成功父进程返回孩子pid,子进程返回0。失败返回-1。

函数:pid_t frok(void); 

#include<stdio.h>
#include<unistd.h>int main()
{printf("Befor pid is %d\n",getpid());pid_t id=fork();if(id==-1){perror("fork()");exit(1);}printf("After:pid is %d,return id is %d \n",getpid(),id);
}

结果: 

1.2写时拷贝(Copy-on-write)

fork() 使父子进程共享相同的内存内容,直到其中一个进程对内存进行修改,这时才会进行拷贝,避免不必要的资源浪费。 

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
int main()
{int a=0;printf("Befor pid is %d\n",getpid());pid_t id=fork();if(id==-1){perror("fork()");exit(1);}printf("After:pid is %d,return id is %d \n",getpid(),id);  }

 此时三个地址:a取地址一样

1.3 虚拟地址存储 

尝试在子进程中修改a的地址后,查看a的地址。

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
int main()
{int a=0;printf("Befor pid is %d,path is %p\n",getpid(),&a);pid_t id=fork();if(id==-1){perror("fork()");exit(1);}if(id==0) {int a=15;printf("After:pid is %d,return id is %d ,path is %p\n",getpid(),id,&a);  }elseprintf("After:pid is %d,return id is %d ,path is %p\n",getpid(),id,&a);}

 三个地址仍然相同?这是为什么呢?

两个虚拟地址相同的原因在于它们位于不同的虚拟页面上,但在各自的虚拟页面内,偏移量相同。因此,尽管它们属于不同的虚拟内存块,最终的虚拟地址值却相同。

2. 进程终止

2.1进程退出情况
  • 代码运行完毕,结果正常
  • 代码运行完毕,结果不正常
  • 进程异常终止
2.2退出方式

如果系统正常终止可以通过$?来查看进程退出码

  • 从main函数返回
  • 调用exit
  • 调用_exit
2.3退出码

每个进程都有一个退出码,0 表示正常退出,非 0 表示出错。

2.4exit函数VS_exit函数
2.4.1exit函数

#include <unistd.h>

#include<stdlib.h>
void exit(int status); 

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{printf("exit");exit(1);}

 2.4.2_exit函数

#include <unistd.h>

#include<stdlib.h>
void _exit(int status); 

#include<stdio.h>
#include<unistd.h>
int main()
{printf("_exit");_exit(1);}
 2.4.3eixt VS_exit

3. 进程等待

3.1进程等待的必要性
  • 之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存
  • 泄漏。
  • 另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。
  • 最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。
  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息
 3.2wait等待

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait(int *status);

返回值:
        成功返回被等待进程pid,失败返回-1。
参数:
        输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

pid_t waitpid(pid_t pid, int *status, int options);

返回值:
        当正常返回的时候waitpid返回收集到的子进程的进程ID;
        如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
        如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
        pid:
                Pid=-1,等待任一个子进程。与wait等效。
                Pid>0.等待其进程ID与pid相等的子进程。
        status:

                输出型参数
                        WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
                        WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:默认为0,表示阻塞等待

                        WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等
待。若正常结束,则返回该子进程的ID。

int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

 

3.3获取子进程status
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{int id=0;int cur=5;id=fork();if(id==-1){perror("fork");}if(id==0){while(cur--){printf("My pid is %d,My ppid is %d\n",getpid(),getppid());}sleep(1);exit(1);}int status=0;int idd=waitpid(id,&status,0);printf("idd is %d,status is %d\n",idd,status);}

3.3.1退出码 

为什么退出码是256而不是1?

  printf("idd is %d,status is %d\n",idd,(status>>8));

3.3.2终止信号 

3.3.3 WIFEXITED

是一个宏值,与&0x7F取得的效果相仿

程序正常运行为:真

程序异常退出为:假

3.3.4WEXITSTATUS

是一个宏值,与(>>8)&&0xFF取得的效果类似

3.4非阻塞查询(wnohang)和阻塞查询(0)

4.总结

 1.Linux下的错误码及描述

0->Success
1->Operation not permitted
2->No such file or directory
3->No such process
4->Interrupted system call
5->Input/output error
6->No such device or address
7->Argument list too long
8->Exec format error
9->Bad file descriptor
10->No child processes
11->Resource temporarily unavailable
12->Cannot allocate memory
13->Permission denied
14->Bad address
15->Block device required
16->Device or resource busy
17->File exists
18->Invalid cross-device link
19->No such device
20->Not a directory
21->Is a directory
22->Invalid argument
23->Too many open files in system
24->Too many open files
25->Inappropriate ioctl for device
26->Text file busy
27->File too large
28->No space left on device
29->Illegal seek
30->Read-only file system
31->Too many links
32->Broken pipe
33->Numerical argument out of domain
34->Numerical result out of range
35->Resource deadlock avoided
36->File name too long
37->No locks available
38->Function not implemented
39->Directory not empty
40->Too many levels of symbolic links
41->Unknown error 41
42->No message of desired type
43->Identifier removed
44->Channel number out of range
45->Level 2 not synchronized
46->Level 3 halted
47->Level 3 reset
48->Link number out of range
49->Protocol driver not attached
50->No CSI structure available
51->Level 2 halted
52->Invalid exchange
53->Invalid request descriptor
54->Exchange full
55->No anode
56->Invalid request code
57->Invalid slot
58->Unknown error 58
59->Bad font file format
60->Device not a stream
61->No data available
62->Timer expired
63->Out of streams resources
64->Machine is not on the network
65->Package not installed
66->Object is remote
67->Link has been severed
68->Advertise error
69->Srmount error
70->Communication error on send
71->Protocol error
72->Multihop attempted
73->RFS specific error
74->Bad message
75->Value too large for defined data type
76->Name not unique on network
77->File descriptor in bad state
78->Remote address changed
79->Can not access a needed shared library
80->Accessing a corrupted shared library
81->.lib section in a.out corrupted
82->Attempting to link in too many shared libraries
83->Cannot exec a shared library directly
84->Invalid or incomplete multibyte or wide character
85->Interrupted system call should be restarted
86->Streams pipe error
87->Too many users
88->Socket operation on non-socket
89->Destination address required
90->Message too long
91->Protocol wrong type for socket
92->Protocol not available
93->Protocol not supported
94->Socket type not supported
95->Operation not supported
96->Protocol family not supported
97->Address family not supported by protocol
98->Address already in use
99->Cannot assign requested address
100->Network is down
101->Network is unreachable
102->Network dropped connection on reset
103->Software caused connection abort
104->Connection reset by peer
105->No buffer space available
106->Transport endpoint is already connected
107->Transport endpoint is not connected
108->Cannot send after transport endpoint shutdown
109->Too many references: cannot splice
110->Connection timed out
111->Connection refused
112->Host is down
113->No route to host
114->Operation already in progress
115->Operation now in progress
116->Stale file handle
117->Structure needs cleaning
118->Not a XENIX named type file
119->No XENIX semaphores available
120->Is a named type file
121->Remote I/O error
122->Disk quota exceeded
123->No medium found
124->Wrong medium type
125->Operation canceled
126->Required key not available
127->Key has expired
128->Key has been revoked
129->Key was rejected by service
130->Owner died
131->State not recoverable
132->Operation not possible due to RF-kill
133->Memory page has hardware error

http://www.mrgr.cn/news/98667.html

相关文章:

  • fedora 42更新了
  • UDP猜数字游戏与TCP文件传输案例解析
  • 【Windows Cmake工程配置Boost库】
  • element-ui自定义主题
  • Java Web 300问
  • Cursor入门教程-JetBrains过度向
  • Serverless集群搭建:Knative
  • 前端基础之《Vue(5)—组件基础》
  • HOW - 项目 link 本地开发库进行调试
  • 【c语言】深入理解指针1
  • 任务的状态
  • 硬件电路设计之51单片机(2)
  • 2.一维卡尔曼滤波(动态模型)
  • leetcode 122. Best Time to Buy and Sell Stock II
  • LeetCode -- Flora -- edit 2025-04-16
  • 深度学习-卷积层(代码+理论)python opencv源码(史上最全)
  • idea中提高编译速度研究
  • ESP8266/32作为AVR编程器(ISP programmer)的使用介绍
  • 基于DS-TWR(双边双向测距)的平面定位MATLAB例程,包含模拟数据生成、距离计算和最小二乘定位(附完整代码,订阅专栏后可直接查看)
  • JWT 鉴权机制 通俗易懂解释版本