当前位置: 首页 > news >正文

【Linux】进程控制(上)

进程创建

fork函数:从已存在进程中创建一个新进程,新进程为子进程,原进程为父进程。

#include <unistd.h>
pid_t fork(void);
返回值:子进程返回0,父进程返回子进程id,出错返回-1.

执行到fork代码后,内核做:

1.分配新的内存块和内核数据结构给子进程
2.将父进程部分数据结构内容拷贝至子进程
3.添加子进程到系统进程列表当中
4.fork返回,开始调度器调度

写时拷贝:父子的代码通常为共享,在不进行写入时,数据也是共享的,当任意一方试图写入,就会以写时拷贝的方式拷贝一份副本。
在这里插入图片描述

进程终止

进程退出场景

代码运行完毕,结果正确
代码运行完毕,结果不正确
代码异常中止

注意:代码异常终止时,本质是代码没有跑完,进程的退出码无意义。
程序出异常时,异常会被系统转换成信号并发送给进程,从而让进程直接退出。
进程常见退出方式
正常终止(echo $?可查看最近一个进程的退出码):

1.从main返回
2.调用exit
3.调用_exit

异常退出:

ctrl+c , 信号终止。

_exit函数

#include <unistd.h>
void _exit(int status);
参数:status定义了进程的终止状态,父进程通过wait来获取该值。

exit函数

#include <unistd.h>
void exit(int status);

exit最后也会调用_exit,但在调用之前,还做了其他工作:

1. 执行用户通过 atexit或on_exit定义的清理函数。
2. 关闭所有打开的流,所有的缓存数据均被写入
3. 调用_exit

在这里插入图片描述
由以上图可知:缓冲区一定不在内核中。
在这里插入图片描述
在这里插入图片描述
printf一定是先把数据写入缓冲区,合适的时候再进行刷新。
退出码:可用return n或exit(n)返回不同的数字,表示不同的出错原因。

进程等待

必要性:

1.僵尸进程无法被杀死,需要通过进程等待来杀掉它,进而解决内存泄漏的问题。
2.我们需要知道父进程派给子进程的任务完成的如何,获取子进程退出信息。

进程等待的方法:
1.wait方法

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int* status);

返回值:成功返回被等待进程pid,失败返回-1.
参数:输出型参数,获取子进程退出状态,不关心则可以设置成NULL。
2.waitpid方法

pid_t waitpid(pid_t pid,int* status,int options);
头文件同上

返回值:
1.当正常返回时为子进程的ID.
2.若设置了选项WNOHANG,且调用中waitpid发现没有已退出的子进程可收集,则返回0.
3.若调用中出错,则返回-1,这时errno会被设置成相应的值指示错误所在。
参数:

pid:pid=-1,等待任一个子进程。与wait等效。pid>0,等待其进程ID与pid相等的子进程。
status:WIFEXITED(status):子进程正常退出时为真。WEXITSTATUS(status):若子进程正常退出,则提取其退出码。
options:0:阻塞等待WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不等待。若正常结束,则返回该子进程ID。

1.若子进程已经退出,调用wait/waitpid时,会立即返回并释放资源,获得子进程退出信息。
2.子进程存在且正常运行时,进程可能阻塞。
3.若不存在子进程,则立即出错返回。
status
只考虑它32bit位的低16位。
在这里插入图片描述

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <sys/types.h>5 #include <sys/wait.h>6 7 #define N 108 9 void RunChild()10 {11     int cnt=5;12     while(cnt--)13     {14         printf("i am a child process,pid:%d,ppid:%d\n",getpid(),ge    tppid());15         sleep(1);16     }17 }18 int main()19 {20     for(int i=0;i<N;i++)21     {22         pid_t id=fork();23         if(id==0)24         {25             RunChild();26             exit(i);                                              27         }28         printf("creat child process:%d success\n",id);29     }30     sleep(10);for(int i=0;i<N;i++)32     {33        // pid_t id=wait(NULL);34         int status=0;35         pid_t id=waitpid(-1,&status,0);//阻塞等待36         if(id>0)37         {38             printf("wait %d success,exit code:%d\n",id,WEXITSTATUS    (status));39         }40     }41     sleep(5);42     return 0;43 }

非阻塞轮询:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>#define N 10
#define TASK_NUM 10typedef void(*task_t)();//定义task_t为函数指针类型。
task_t tasks[TASK_NUM];//定义tasks为函数指针数组。
void task1()
{printf("这是一个执行打印日志的任务, pid: %d\n", getpid());
}void task2()
{printf("这是一个执行检测网络健康状态的一个任务, pid: %d\n", getpid());
}void task3()
{printf("这是一个进行绘制图形界面的任务, pid: %d\n", getpid());
}
int AddTask(task_t t);
void InitTask()
{for(int i=0;i<TASK_NUM;i++){tasks[i]=NULL;//初始化数组内的每一个函数指针都为空。}AddTask(task1);AddTask(task2);AddTask(task3);
}
int AddTask(task_t t)
{int pos=0;for(;pos<TASK_NUM;pos++){if(!tasks[pos])break;//找到数组内元素为空的位置准备赋值。}if(pos==TASK_NUM){return -1;//数组已满则无法继续添加。}tasks[pos]=t;return 0;
}
void ExecuteTask()
{for(int i=0;i<TASK_NUM;i++){if(!tasks[i]){continue;}tasks[i]();//若任务为空,则进入下一次循环,不为空,则调用。}
}
int main()
{pid_t id=fork();if(id<0){perror("fork");return 1;}else if(id==0){int cnt=5;while(cnt--){printf("I am child,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);sleep(1);}exit(11);}else{int status=0;InitTask();while(1){//轮询pid_t ret=waitpid(id,&status,WNOHANG);if(ret>0){if(WIFEXITED(status)){printf("进程是正常跑完的,退出码:%d\n",WEXITSTATUS(status));}else{printf("进程出异常了!\n");}}else if(ret<0){//调用这个函数的过程中出错。printf("wait failed!\n");break;}else{ExecuteTask();usleep(500000);}}}return 12;
}
http://www.dtcms.com/a/457238.html

相关文章:

  • 湖北省建设网站wordpress商务套餐
  • 网站建设推广的软文邢台建站企业邮箱
  • C++11并发支持库
  • 广东省省考备考(第一百一十八天10.8)——言语、资料分析、数量关系(强化训练)
  • 临沂网站制作页面如何查一个网站有没有做外链
  • 基于websocket的多用户网页五子棋(八)
  • Elastic 被评为 IDC MarketScape《2025 年全球扩展检测与响应软件供应商评估》中的领导者
  • 如何利用Python呼叫nexxim.exe执行电路模拟
  • APM学习(3):ArduPilot飞行模式
  • h5制作开发价目表常用seo站长工具
  • 忻州建设公司网站他达那非副作用太强了
  • pytest详细教程
  • 订单超时方案的选择
  • Redis 集群故障转移
  • 虚拟专用网络
  • 网站制作公司网站建设网站膳食管理东莞网站建设
  • Linux小课堂: 从零到上手的指南
  • DrissionPage防检测
  • 三亚官方网站建设ps如何做网页设计
  • Java体系总结——从基础语法到微服务
  • 深圳网站建设李天亮网站怎么做构成
  • Word卡顿,过很久才弹窗网络连接失败解决办法
  • 古典网站建设睢宁招标网官方
  • 告别物流乱象:商贸物流软件如何实现全流程可视化管理​
  • Ubuntu 20.04 安装mysql-5.7.9
  • 二、排版格式与注释
  • 计组2.2.1——加法器,算数逻辑单元ALU
  • 东莞网站建设公司注册郑州企业网站排名
  • 2025-10-08 Python 标准库 4——内置类型:数字类型
  • java ArrayList的add方法是插入到最后吗