【Linux】进程控制(1)进程创建、终止
写时拷贝是实现数据独立性的核心机制进程加载数据和代码到内存里代码段初始权限是只读的但是数据段初始权限是可读写的。但是一旦创建子进程共享代码和数据OS就会强制改变数据的权限为只读对于父子进程都是一旦有父进程或者是子进程尝试改变数据就会被操作系统知道操作系统从而对修改后的数据重新分配物理内存页。强制将权限改为只读的原因就是要让OS知道有进程要对这个数据做修改了。如果是原来的读写权限OS是没有办法知道的。二、进程终止2.1 进程终止情况进程终止会有几种情况我们运行一个程序当代码跑完的时候这个进程肯定终止了还有代码没有跑完发生了报错这个时候进程也会被强制终止。它们总体可以概括为以下三种代码跑完结果正确。代码跑完结果错误。代码没有跑完发生异常。前面两种是正常终止程序执行完毕主动退出无论结果是对是错OS会对资源进行回收而第三种是异常终止程序代码未执行完毕就被动退出。一个进程正常终止但是结果是对的还是错的呢我们应该如何知道----这就得提到在代码执行结束的时候会return 0了但是为什么要返回0这代表什么—这个0其实就是一个退出码返回0就是代表执行成功如果返回的是其他的数字则代表执行不成功。进程异常终止本质是收到了操作系统发送的终止信号每个信号都有唯一的数字编号。0对应无信号其他数字对应不同的信号我们可以用kill -l 进行查看。比如下面的信号9就是之前使用过的用来杀死进程的信号。在这里插入图片描述如此上面三种进程终止的情况可以用退出码和sign信号来表示代码跑完结果正确。----退出码为0sign数字编号为0。代码跑完结果错误。----退出码不为0sign数字编号为0。代码未跑完发生异常。----sign数字编号不为0退出码无效。ctrl c 对应的是信号2中断信号。2.2 退出码我们可以通过查看这个退出码来了解进程执行的是否成功不同的退出码对应不同的退出状态。0一般代表的是执行成功其他的退出码代表的都是执行不成功不成功的理由各不相同。退出码分为两类一类是系统提供的退出码系统另一类是写程序的时候自定义的退出码比如通过宏进行定义。以下是Linux Shell中的主要退出码在这里插入图片描述strerror我们可以用strerror函数包含在string.h头文件里来获取退出码所对应的描述代码语言javascriptAI代码解释1 #includestdio.h 2 #includestring.h 3 4 5 int main() 6 { 7 int i 0; 8 for (; i 300; i) 9 { 10 printf(%d-%s\n, i, strerror(i)); 11 } 12 return 0; 13 }在这里插入图片描述echo $?获取退出码$?会存储上一个前台执行的进程的退出码可以用echo进行查看。在这里插入图片描述在这里插入图片描述第一张是命令执行成功所查询到的退出码如果我们用cd去进入一个不存在的文件那么这个命令就执行不成功退出码自然就不是0。2.3 让进程退出的方法exit()终止整个进程并刷新缓存区。它不光是退出当前函数。_exit()终止整个进程但不刷新缓存区。exit()是一个库函数而_exit()是一个系统调用函数exit()比_exit()函数多了一个刷新缓存区的功能其实exit函数就是对_exit()函数的一个封装。代码语言javascriptAI代码解释#includestdio.h 17 #includeunistd.h 18 #includestdlib.h 19 int main() 20 { 21 printf(hello world!); 22 sleep(1); 23 exit(0);//_exit(0); 24 }对于同一段代码exit()执行结果在这里插入图片描述_exit()执行结果在这里插入图片描述printf语句里面我们没有使用换行符\n来刷新缓冲区可以看到exit是有刷新缓冲区的而_exit没有。这也说明刷新缓冲区的工作并不是由内核完成的毕竟exit是库函数而_exit才是系统调用函数。return退出当前函数而非终止整个进程。在我们写一些函数的时候返回一个值会用return这个时候会退出当前函数而exit/_exit是直接终止这个进程。可以用此段代码进行测试代码语言javascriptAI代码解释#include stdio.h #include stdlib.h // 普通子函数 void test() { printf(进入test函数\n); // 场景1用return仅退出test函数进程继续 return; // 场景2用exit()直接终止整个进程后续代码都不执行 // exit(0); } int main() { printf(进入main函数\n); test(); // 调用test函数 printf(test函数执行完回到main继续运行\n); // 场景1会执行场景2不会 return 0; }今天的分享就到此结束啦,如果对读者朋友们有所帮助的话,可否留下宝贵的三连呢~~让我们共同努力, 一起走下去!