ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【Linux详解】进程等待 | 非阻塞轮询 [打印本页]

作者: 雁过留声    时间: 2024-7-11 00:58
标题: 【Linux详解】进程等待 | 非阻塞轮询
引入
为什么?是什么?怎么办
是什么?

进程等待是指父进程暂停自己的实行,直到某个特定的子进程结束或发生某些特定的事件。
为什么?


怎么办

wait 函数
  1. #include <sys/types.h>
  2. #include <sys/wait.h>
  3. pid
  4. _t wait(int* status);
复制代码
测试:
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/wait.h>
  7. int main (
  8.     void
  9.     )
  10. {
  11.     pid
  12. _t id = fork();
  13.     if (id == 0) {
  14.         // child
  15.         while (1) {
  16.             printf("我是子进程,我正在运行... Pid: %d\n", getpid
  17. ());
  18.             sleep(1);
  19.         }
  20.     }
  21.     else {
  22.         printf("我是父进程: pid
  23. : %d,我将耐心地等待子进程!\n", getpid
  24. ());
  25.         sleep(20);   // 为了便于观察,我们让父进程休眠20s
  26.         // 苏醒后,父进程执行 wait,耐心地等待子进程
  27.         pid
  28. _t ret = wait(NULL);  // 暂且将status参数设置为NULL
  29.         if (ret < 0) {
  30.             printf("等待失败!\n");
  31.         }
  32.         else {
  33.             printf("等待成功!\n");   // 此时 Z → X
  34.         }
  35.         sleep(20);  // 子进程退出后,再让父进程存在一段时间
  36.     }
  37. }
复制代码

为什么是瓜代型,不是一个实行完?//相识循环的细节
在 fork 创建子进程后,父进程会首先实行并打印这条信息,其中 <父进程的pid
> 是父进程的进程ID。截不下就没截了

通过这种方式,父进程和子进程可以或许并发地实行各自的任务,并且我们通过延迟父进程的退出能观察到子进程的连续运动。
整个程序实行流程如下:

之后,父进程再休眠20秒并继续存在一段时间退却出

waitpid


刚才讲的 wait 并不是主角,因为其功能比力简单,在进程等待时用的更多的是 waitpid

waitpid
可以把 wait 完全包含,wait 是 waitpid
的一个子功能。

参数

返回值

   Z状态,其本质上就是将自己的 task_struct 维护起来(代码可以释放,但是 task_struct 必须维护)。所谓的 wait/waitpid
的退出信息,实际上就是从子进程的 task_struct 中拿出来的,即 从子进程的 task_struct 中拿出子进程退出的退出码,拷贝到父进程中
  

  status

该参数是一个 输出型参数 (即通过调用该函数,从函数内部拿出来特定的数据)。整数的低 16 位,其中又可以分为 最低八位次低八位(具体细节看图):

1.次低八位:拿子进程退出码

  1. #include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/wait.h> int main (    void    ) {    pid
  2. _t id = fork();    if (id == 0) {        int cnt = 5;   // 循环5次        // child        while (1) {            // 五秒之内运行状态            printf("我是子进程,我正在运行... Pid: %d\n", getpid
  3. ());            sleep(1);             // 五秒之后子进程制止            cnt--;            if (cnt == 0) {                break;             }        }         exit(233);   // 方便辨识,退出码我们设置为233,这是我们的预期结果    }    else {        printf("我是父进程: pid
  4. : %d,我将耐心地等待子进程!\n", getpid
  5. ());                // ***** 使用waitpid
  6. 进行进程等待        int status = 0;  // 接收 waitpid
  7. 的 status 参数         pid
  8. _t ret = waitpid
  9. (id, &status, 0);        if (ret > 0) {   // 等待成功            printf (                "等待成功,ret: %d, 我所等待的子进程退出码: %d\n",                 ret,                (status>>8)&0xFF            );        }     }}
复制代码
status 并不是整体使用的,而是区域性使用的,我们要取其次低八位。我们可以用 位操纵 来完成,将 status右移八位再按位与上 0XFF,即 (status>>8)&0xFF ,就可以提取到 status 的次低八位了。

waitpid
经过体系调用,来读取子进程的pcb(eg. task_st…),这是为什么呢
   操纵体系不相信任何人,父进程用户无法直接读取子进程的 pcb ,要通过体系调用的接口
  

  2.初识 core dump(焦点转储)


它是操纵体系在进程收到某些信号而制止运行时,将此时进程地址空间的内容以及有关进程状态的其他信息写出的一个磁盘文件。现在只需要知道,该信息是用于调试的。
3.最低七位:提取子进程的退出信号

刚才我们讲的 wait/waitpid
和次低八位的时侯,都是关于进程(exit) 的 正常退出。
假如进程 非常退出 呢?我们来模仿一下进程的非常退出。





欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4