Linux之进程控制

11 篇文章 0 订阅

今天分享一下关于Linux进程控制的知识点

1.进程创建

fork( )函数

#include<unistd.h>
pid_t fork(void);
通过返回值判断是否创建成功,分流父子进程
对于父进程,返回的是子进程的pid>0
对于子进程,返回的是0

创建过程:通过复制调用父进程,创建一个新的进程(子进程)。
复制的父进程的pcb,复制了父进程大部分的数据,因此代码共享,但是数据独有,所以是一种写实拷贝。
因为在父子不再写入数据时,父子的数据是共享的,但是一方试图写入的话,便用写实拷贝的方式各自一份副本。
同时在这里也提到一下vfork( )这个进程创建函数:
子进程与父进程公用同一块虚拟地址空间—子进程先运行,等到子进程exit退出或者程序替换后,父进程才开始运行,子进程return后资源释放,父进程则调用栈混乱,因此vfork创建子进程不能在main中return退出。
vfork的存在意义:
快速创建子进程,并且子进程是专门用来运行其他程序,公用地址空间可以减少子进程数据拷贝父进程的消耗,因此速度快。但是vfork逐渐被淘汰了,因为fork函数的写实拷贝技术的出现。

xshell6中vfork( )函数代码实现部分:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 
  5 int main()
  6 {
  7     int pid = vfork();
  8     if(pid==0){
  9         printf("child---%d\n",getpid());
 10     }
 11     else{
 12         printf("parents---%d\n",getpid());
 13     }
 14     return 0;
 15 
 16     while(1){
 17         printf("---%d\n",getpid());
 18         sleep(1);
 19     }
 20     return 0;
 21 }

2.进程等待

进程等待就是为了等待子进程的退出,避免产生僵尸进程!
父进程不知道子进程什么时候退出,所以忙其他事情,这时候如果子进程退出了,操作
系统的通知,父进程可能就没有关注到,子进程成为僵尸进程,僵尸进程过多的话就会导致资源泄漏,无法创建创建新的子进程,危害很大。

关于僵尸进程概念一节请参考我的另一篇博客:
https://blog.csdn.net/Python_programer/article/details/88921155

wait(int)—阻塞函数;等待任意一个子进程退出。
wait(NULL)表示不关心子进程的返回值,让操作系统直接释放子进程。
阻塞:为了完成功能发起调用,如果当前不具备完成条件,则一直等待,直到完成后返回。
非阻塞:为了完成功能发起调用,如果当前不具备完成条件,则立即报错返回。
阻塞与非阻塞的区别:调用功能当前不具备完成条件是否立即返回。
pid_t waitpid(pid_t pid,int* statu,int opt)
pid:
-1 : 等待任意子进程退出
0 :等待指定子进程退出
status :用于获取退出原因
options:
WNOHANG 将waitpid设置为非阻塞
函数返回值: -1 错误 0 子进程没有退出 >0 退出子进程的pid
可以等待任意一个子进程退出或者等待指定子进程退出,waitpid可以通过opt将操作设置为非阻塞。
获取子进程status:
status不能简单的当作整形来看待,可以当作位图来看待如下图所示,只研究status低16比特位。
在这里插入图片描述
低十六位的高八位存放子进程退出的返回值。
低十六位的低八位的高一位叫1b(core dump标志) 程序异常退出时,是否保存运行信息。
低七位为存储异常退出信号值。
如何获取子进程退出码:(statu>>8)&0xff(status为int型)。
判断程序是否正常退出:status&0x7f --异常信号值为0,证明程序是正常退出,否则异常退出。
WIFEXITED(status):判断进程是否正常退出,正常退出则返回true
WEXITSTATUS(status):在进程正常退出时,获取子进程退出码

if(WIFEXITED(status)){
printf(“退出值为 %d\n”, WEXITSTATUS(status));
}

WIFSIGNALED(status)为非0 表明进程异常终止。
若上宏为真,此时可通过WTERMSIG(status)获取使得进程退出的信号编号

if(WIFSIGNALED(status)){
printf(“使得进程终止的信号编号: %d\n”,WTERMSIG(status));
}

xshell6中waitpid()函数代码实现部分:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 
  5 int main()
  6 {
  7     int pid = fork();
  8     if(pid<0){
  9         perror("fork error!");
 10         exit(-1);
 11     }
 12     else if(pid==0){
 13         sleep(5);
 14         exit(255);
 15     }
 16 
 17     int statu;
 18     int ret;
 19     while((ret = waitpid( pid, &statu, WNOHANG))==0){
 20         printf("忙其他的事!\n");
 21         sleep(1);
 22     }
 23     if(!(statu & 0xf7)){
 24         printf("%d--%d---the child exit code:%d\n",ret,pid,
 25             (statu>>8)&0xff);
 26     }
 27     if(WIFEXITED(statu)){
 28         printf("the child exit code:%d\n",WEXITSTATUS(statu));
 29     }
 30     if(WIFSIGNALED(statu)){
 31         printf("the exit signal:%d\n",WTERMSIG(statu));
 32     }
 33     while(1){
 34         printf("-------\n");
 35         sleep(1);
 36     }
 37     return 0;
 38 }

3.进程终止

终止场景:
正常退出,结果符合预期
正常退出,结果不符合预期
异常退出
终止方式: 二者的区别要分清!
main函数中return
exit()是一个库函数,在退出前会刷新缓冲区,做退出的收尾工作
_exit()是一个系统调用接口,直接退出,释放资源
返回值:
echo $? 可以查看进程返回值
错误编号:每个系统调用执行完毕后都会重置进程中errno这么一个全局变量,这个全局变量
中存储的就是档次调用的系统调用接口错误编号,当系统调用接口出错用户就可以通过这个errno获取系统调用的错误原因。
void perror(const char* s);
char* strerror(int errnum);

xshell6中exit()函数代码实现部分:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<errno.h>
  6 
  7 int main()
  8 {
  9     int pid = fork();
 10     if(pid<0){
 11        perror("fork error");
 12        printf("fork error %s\n",strerror(errno));
 13     }
 14     printf("-------");
 15     int i=0;
 16     for(;i<256;i++)
 17     {
 18         printf("%s\n",strerror(i));
 19     }
 20     sleep(3);
 21     _exit(255);
 22     exit(0);
 23     return 0;
 24 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值