河北特定网站建设推荐,海南省住房和建设厅网站,做图片的软件带字图片,网站备案后 如何建设#x1f4d8;北尘_#xff1a;个人主页 #x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上#xff0c;不忘来时的初心 文章目录 一、进程创建1、fork函数初识2、fork函数返回值3、写时拷贝4、fork常规用法5、fork调用失败的… 北尘_个人主页 个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上不忘来时的初心 文章目录 一、进程创建1、fork函数初识2、fork函数返回值3、写时拷贝4、fork常规用法5、fork调用失败的原因 二、进程终止1、进程退出场景2、进程常见退出方法3、_exit函数4、exit函数5、return退出6、退出码VS错误码 一、进程创建
1、fork函数初识
在linux中fork函数时非常重要的函数它从已存在进程中创建一个新进程。新进程为子进程而原进程为父进程。 #include unistd.h pid_t fork(void); 返回值自进程中返回0父进程返回子进程id出错返回-1 进程调用fork当控制转移到内核中的fork代码后内核做
分配新的内存块和内核数据结构给子进程将父进程部分数据结构内容拷贝至子进程添加子进程到系统进程列表当中fork返回开始调度器调度 当一个进程调用fork之后就有两个二进制代码相同的进程。而且它们都运行到相同的地方。但每个进程都将可以开始它们自己的旅程看如下程序。
int main( void )
{pid_t pid;printf(Before: pid is %d\n, getpid());if ( (pidfork()) -1 )perror(fork()),exit(1);printf(After:pid is %d, fork return %d\n, getpid(), pid);sleep(1);return 0;
}这里看到了三行输出一行before两行after。进程29768先打印before消息然后它有打印after。另一个after 消息有29769打印的。注意到进程29769没有打印before为什么呢如下图所示
所以fork之前父进程独立执行fork之后父子两个执行流分别执行。注意fork之后谁先执行完全由调度器决定。
2、fork函数返回值
子进程返回0。 父进程返回子进程的pid。
3、写时拷贝
通常父子代码共享父子再不写入时数据也是共享的当任意一方试图写入便以写时拷贝的方式各自一份副本。具体见下图: 问题是进程是在运行的OS是如何知道要进行写时拷贝的。
原来是在今天fork之后OS会将父子进程的页表权限设置为只读当父子进程其中一个去修改时会报错。 这里的报错有两种情况 一是真的出错了 二是权限关闭了 所以OS会去判断如果是第二种情况OS就会让在物理内存中发生写时拷贝。
4、fork常规用法
一个父进程希望复制自己使父子进程同时执行不同的代码段。例如父进程等待客户端请求生成子 进程来处理请求。 一个进程要执行一个不同的程序。例如子进程从fork返回后调用exec函数。
5、fork调用失败的原因
系统中有太多的进程 实际用户的进程数超过了限制
二、进程终止
1、进程退出场景 存在三种情况 2、进程常见退出方法 正常终止可以通过 echo $? 查看进程退出码 从main返回调用exit_exit 异常退出 ctrl c信号终止
3、_exit函数
#include unistd.h
void _exit(int status);参数status 定义了进程的终止状态父进程通过wait来获取该值
说明虽然status是int但是仅有低8位可以被父进程所用。所以_exit(-1)时在终端执行$?发现返回值 是255。
4、exit函数
#include unistd.h
void exit(int status);exit最后也会调用exit, 但在调用exit之前还做了其他工作
执行用户通过 atexit或on_exit定义的清理函数。关闭所有打开的流所有的缓存数据均被写入调用_exit 5、return退出
return是一种更常见的退出进程方法。执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返 回值当做 exit的参数。
6、退出码VS错误码 退出码 退出码就是进程运行结束返回的数字 其中0代表成功 0代表出错了具体的数值代表不同的原因 我们可以发现第一次看进程退出码为10后来就成了0这是因为错误码只会保存最新的一次后来由于上面指令执行成功了所以变为了0。
main函数的退出码是可以被父进程获取的用来判断子进程的运行结果 错误码 错误码通常是衡量一个库函数或者一个系统调用一个一个函数的调用情况 下面我们来验证一个结论进程出现异常的本质是由于受到对应的信号自己终止了。 最后我们可以得出父进程通过两个数字来判断子进程是否受到异常结束或者成功输出。