欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > Linux进程控制

Linux进程控制

2025/2/26 13:50:22 来源:https://blog.csdn.net/2302_80378107/article/details/144488494  浏览:    关键词:Linux进程控制

1.进程终止

进程终止的本质是释放系统资源,就是释放进程申请的相关内核数据和对应的数据和代码。

进程退出场景

代码运行完毕,结果正确

代码运行完毕,结果错误

代码异常终止

进程常见退出办法

正常终止:

1.从main返回

2.调用exit

3._exit

异常退出:
ctrl+c 信号终止

退出码

退出码(退出状态)可以告诉我们最后一次执行的命令的状态。在命令结束后,可以知道命令是成功完成还是以错误结束的,基本思想是,程序返回退出代码0表示执行成功,没有问题。代码1或0以外的任何代码都视为不成功。

退出码0表示命令执行无误,这是完成命令的理想状态

退出码1可以解释为不被允许的操作,例如没有sudo情况下使用apt或者yum;例如除以0等操作也会返回错误代码1。

130(SIGINT或^C)和143(SIGTERM)等终止信号是非常典型的,它们属于128+n信号,其中n代表终止码

可以通过strerror函数获取退出码对应的描述

指令显示退出码

echo $?

_exit函数

#include<unistd.h>

void _exit(int status);

参数:status定义了进程的终止状态,父进程通过wait获取该值

注意:虽然status是int,但是仅有低八位可以被父进程所用。所以_exit(-1)时。在终端执行 echo $?时返回值是255.

exit函数

#include<unistd.h>

void exit(int status);

exit函数里面是调用了_exit,但exit函数还做了其它事情:

1.执行用户通过atexit或on_exit定义的清理函数

2.关闭所有打开的流,所有的缓存数据均被写入

3.调用_exit 

 _exit函数是系统层面的,在任何地方调用这个函数都会结束整个进程,而exit在子进程调用不会影响父进程,会把退出码返回给父进程

 

代码示例:

int main()
{
printf("hello");
exit(0);
}
运⾏结果:
[root@localhost linux]# ./a.out
hello[root@localhost linux]#
int main()
{
printf("hello");
_exit(0);
}
运⾏结果:
[root@localhost linux]# ./a.out
[root@localhost linux]#

return退出

return是一种更常见的退出进程方法。执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值做exit的参数。

进程等待必要性

子进程退出,父进程如果不理会,就可能造成僵尸进程问题,进而造成内存泄漏

另外,进程一旦变成僵尸状态,就刀枪不如了,kill -9也无能为力了,无法杀死一个已经死去的进程。

最后,父进程派给子进程的任务完成的如何,是需要知道的。子进程运行完成,结果对还是不对,或者是否正常退出。

父进程通过等待的方式,回收子进程资源,获取子进程退出的信息

进程等待的方法

wait方法

#include<sys/types.h>

#include<sys/wait.h>

pid_t wait(int* status);

返回值:

        成功就返回被等待进程pid,失败返回-1

参数:

        输出型参数,获取子进程退出状态,不关心可以设置为NULL

waitpid方法

#include<sys/types.h>

#include<sys/wait.h>

1

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

返回值:

        当正常返回的时候waitpid返回收集到的子进程的进程ID;

        如果设置了选项WNOHANG,而调用中发现没有已经退出可收集,则返回0;

        如果调用中出错,则返回-1,这时error会被设置成相应的值以指示错误所在

参数:

        pid:

                pid=-1,等待任意一个子进程,与wait等效

                pid>0,等待其进程ID与pid相等的子进程

        status:输出型参数

                      WIFEXITED(status):若为正常终止子进程返回的状态,则为真(查看进程是否正常退出)

                      WEXITSTATUS(status):若WIFEXITED非零,提取子进程的退出码(查看进程的退出码)

        option:默认为0,表示阻塞等待

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

如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。

如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。

如果子进程不存在,则立刻出错返回。

如果子进程结束的话,父进程会阻塞直到子进程结束才继续执行父进程代码

获取子进程status

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。

如果传递NULL,表示不关心子进程的退出信息状态。

操作系统会根据该参数,将子进程的退出信息反馈给父进程

status不能简单的当作整型来看待,可以当作位图来看待,具体细节下图(为status低16位)

若进程正常结束则最低的七位为0。

对于32位的然后得到退出状态的8位,先右移八位然后&0xFF,这样只有最低八位是有效的,其余制成0了。

 

进程之间是独立的,父进程是如何得到子进程的退出码?因为waitpid是系统的,系统是可以得到进程的信息的,然后再给父进程,父进程就得到了子进程的信息 

 

代码示例:

  1 #include<unistd.h>2 #include<sys/wait.h>3 #include<stdio.h>4 #include<stdlib.h>5 #include<string.h>6 #include<errno.h>7 8 int main()9 {10         pid_t pid;11         if((pid=fork())==-1)12         {13                 perror("fork fail:");14                 exit(1);15         }16         if(pid == 0)17         {18                 sleep(2);19                 exit(10);20         }21         else22         {23                 int st;24                 int ret=wait(&st);25                 if(ret>0&&(st&0x7F)==0)26                 {27                         printf("child exit code:%d\n",(st>>8)&0xFF);28                 }29                 else if(ret>0)30                 {31                         printf("sig code:%d\n",st&0x7F);32                 }33         }34 35 36 }

阻塞与非阻塞等待

进程的阻塞等待方式:

一直等子进程结束,不干别的
 

  1 #include<unistd.h>2 //#include<vector>3 #include<sys/wait.h>4 #include<stdio.h>5 #include<stdlib.h>6 7 8 int main()9 {10         pid_t pid;11         pid= fork();12         if(pid ==0)13         {14                 printf("child is run,pid is :%d\n",getpid());15                 sleep(5);16                 exit(257);17         }18         else19         {20                 int status =0;21                 pid_t ret=waitpid(-1,&status,0);//阻塞式等待22                 printf("waiting\n");23                 if(WIFEXITED(status)&&ret==pid)24                 {25                         printf("success,child return code is:%d\n",WEXITSTATUS(status));26 27                 }28                 else29                 {30                         printf("wait fail");31                         return 1;32                 }33         }34         return 0;35 36 37 }

非阻塞状态

这个状态父进程可以不用只等待子进程,可以边等边干别的事情

#include <sys/wait.h>2 #include <stdlib.h>3 #include <string.h>4 #include <errno.h>5 #include<stdio.h>6 #include<unistd.h>7 //#include<vector>8 9 typedef void (*handler_t)(); // 函数指针类型10 std::vector<handler_t> handlers; // 函数指针数组11 void fun_one() {12         printf("这是⼀个临时任务1\n");13 }14 void fun_two() {15         printf("这是⼀个临时任务2\n");16 }17 void Load() {18         handlers.push_back(fun_one);19         handlers.push_back(fun_two);20 }21 void handler() {22         if (handlers.empty())23                 Load();24         for (auto iter : handlers)25                 iter();26 }27 int main() {28         pid_t pid;29         pid = fork();30         if (pid < 0) {31                 printf("%s fork error\n", __FUNCTION__);32                 return 1;33         }34          else if (pid == 0) { // child35                 printf("child is run, pid is : %d\n", getpid());36                 sleep(5);37                 exit(1);38                 }39         else {40                 int status = 0;41                 pid_t ret = 0;42                 do {43                         ret = waitpid(-1, &status, WNOHANG); // ⾮阻塞式等待44                         if (ret == 0) {45                                 printf("child is running\n");46                         }47                         handler();48                 } while (ret == 0);49                 if (WIFEXITED(status) && ret == pid) {50                         printf("wait child 5s success, child return code is :%d.\n",51                         WEXITSTATUS(status));52}53                 else {54                         printf("wait child failed, return.\n");55                         return 1;56                 }57         }58         return 0;59 }

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com