进程相关及守护进程

embedded/2024/10/15 4:24:12/

一、进程

1.1 wait / waitpid 函数的使用

#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *wstatus);
功能:阻塞等待子进程结束,为子进程回收资源
参数:wstatus:子进程退出的状态--如果不关注,可以传NULL0~6:bit位,保存的是中断进程的信号号8~15:bit位,保存的是进程退出的状态WIFEXITED(wstatus):如果进程是正常退出(是否是通过调用exit()函数退出的),返回真WEXITSTATUS(wstatus):获取进程退出的状态,0~255,必须在WIFEXITED返回为真的情况下使用WIFSIGNALED()wstatus:如果进程是被信号中断,这个宏返回trueWTERMSIG(wstatus):返回中断信号进程的信号号,必须在WIFSIGNALED返回为真的情况下使用
返回值:成功返回回收到的子进程的pid,失败返回-1,置位错误码pid_t waitpid(pid_t pid,int *wstatus,int options);
功能:回收子进程的资源
参数:pid:< -1:回收组id为pid的绝对值的子进程的资源传参:-123456,那么会回收组id为123456的子进程的资源-1:回收任意子程序的资源‘0:回收同一进程组的子进程的资源> 0 :回收进程pid == 参数pid,的子进程的资源通过进程的pid,指定回收某个子进程的资源wstatus:子进程退出的状态 -- 如果不关注,可以传NULL0~7:bit位保存的是中断进程的信号号8~15:bit位保存的是进程退出的状态。WIFEXITED(wstatus):如果进程是正常退出(是否是通过调用exit()函数退出的)),返回真WEXITSTATUS(wstatus):获取进程退出的状态,0~255,必须在WIFEXITED返回真的情况下使用WIFSIGNALED(wstatus):如果进程是被信号中断,这个宏返回trueWTERMSIG(wstatus):返回中断进程的信号号,必须在WIFSIGNALED返回真的情况下使用
options:0:表示阻塞回收子进程的资源WNOHANG:非阻塞回收子进程的资源返回值:成功返回回收到的子进程的pid,失败返回-1wait(&wstatus)等价于waitpid(-1,&wstatus,0)
wait(NULL)等价于waitpid(-1,NULL,0)

wait函数的使用实例(回收资源不关注子进程的退出状态)

#include <my_head.h>int main(int argc,const char *argv[]){pid_t ret = 0;ret = fork();if(-1 == ret){PRINT_ERR("fork error");}else if(0 == ret){//子进程sleep(20);printf("子进程,要死了\n");exit(100);//退出的状态为100}else{//父进程//回收资源,不关注子进程的退出状态printf("父进程\n");wait(NULL);//传参NULL,阻塞回收子进程的资源,不关注子进程的状态printf("父进程回收子进程资源完毕\n");sleep(5);printf();}return 0;
}

 运行结果

wait函数的使用实例(回收资源关注子进程的退出状态)

#include <my_head.h>int main(int argc,const char *argv[]){pid_t ret = 0;ret = fork();if(-1 == ret){PRINT_ERR("fork error");}else if(0 == ret){//子进程sleep(5);printf("子进程,要死了\n");exit(100);//退出的状态为100}else{//父进程//回收资源,关注子进程的退出状态int wstatus = 0;pid_t ret;int status,signo;ret = wait(&wstatus);printf("回收到的子进程pid = %d\n",ret);if(WIFEXITED(wstatus)){status = WEXITSTATUS(wstatus);printf("子进程退出的状态值是%d\n",status);}if(WIFSIGNALED(wstatus)){signo = WTERMSIG(wstatus);printf("中断子进程的信号号%d\n",signo);}}return 0;

运行结果:

waitpid使用实例(阻塞方式回收子进程资源,不关注进程退出状态

#include <my_head.h>int main(int argc,const char *argv[]){pid_t ret = 0;ret = fork();if(-1 == ret){PRINT_ERR("fork error");}else if(0 == ret){//子进程sleep(5);printf("子进程,要死了\n");exit(100);//退出的状态位100}else{//父进程//回收资源,不关注子进程退出状态printf("我是父进程\n");waitpid(-1,NULL,0);//传参1NULL,不关注子进程退出状态,阻塞回收子进程的资源printf("父进程回收子进程资源完毕\n");sleep(5);printf("父进程死了\n");}return 0;
}

运行结果:

waitpid使用实例(非阻塞方式回收子进程资源,关注进程退出状态)

#include <my_head.h>int main(int argc,const char *argv[]){pid_t ret = 0;ret = fork();if(-1 == ret){PRINT_ERR("fork error");}else if(0 == ret){//子进程sleep(5);printf("子进程,要死了\n");exit(100);//退出的状态位100}else{//父进程int wstatus = 0;pid_t ret;int sstatus,signo;while(1){printf("我是父进程\n");//非阻塞回收子进程资源,WNOHANGret = waitpid(-1,&wstatus,WNOHANG);if(ret != 0&&ret != -1){printf("回收的子进程pid为%d\n",ret);if(WIFEXITED(wstatus)){sstatus = WEXITSTATUS(wstatus);printf("子进程退出的状态值%d\n",wstatus);}if(WIFSIGNALED(wstatus)){signo = WTERMSIG(wstatus);printf("中断子进程信号号%d\n",signo);}}sleep(1);}  }return 0;
}

运行结果:子进程是否运行完不影响父进程的运行,父进程反复判断,当子进程死了,父进程就回收子进程资源,然后继续运行

1.2 system函数的使用

#include <stdlib.h> --- 所需头文件
int system(const char *command);
功能:通过fork创建一个子进程,在子进程中执行command命令
参数:command:要执行的命令,执行shell脚本,shell命令,可执行程序等
返回值:1、如果command为NULL,或者shell可用,返回0,如果不可用返回非0的数值2、如果子进程无法被创建,那么返回-1,置位错误码3、如果command不可以被执行,返回状态码1274、如果所有的command都执行成功,会返回最后一个shell的返回值。

system使用实例

#include <my_head.h>int main(int argc,const char *argv[]){int ret = 0;//使用system执行命令ret = system("ls");return 0;
}

运行结果:

#include <my_head.h>int main(int argc,const char *argv[]){int ret = 0;//使用system执行命令ret = system("lcdsc");//shell不可用,返回非0数值printf("ret = %d\n",ret);return 0;
}

运行结果:

#include <my_head.h>int main(int argc,const char *argv[]){int ret = 0;//使用system执行多个命令system("ls;pwd");//方式1:使用;作为分隔符,多个命令都会被执行(不论成功失败)return 0;
}

运行结果:

#include <my_head.h>int main(int argc,const char *argv[]){int ret = 0;//使用system执行多个命令system("lssq&&pwd");//方式2:使用&&作为分隔符,多个命令都会被执行,//只要有一个失败,后面的命令都不会被执行return 0;
}

运算结果:

#include <my_head.h>int main(int argc,const char *argv[]){int ret = 0;//使用system执行多个命令system("lssq||pwd||ls");//方式2:使用||作为分隔符,//只要有一个命令执行成功,后面命令则不会再执行return 0;
}

运行结果:

1.3 守护进程

1.3.1 守护进程的概念

        随着系统的启动而启动,睡着系统的终止而终止,脱离中断运行。

就是系统的服务。

1.3.2 守护进程(daemon)的创建流程

        1、创建一个孤儿进程(为了脱离终端)

        2、设置会话id,创建一个新的会话,新会话即新终端,此终端在后台运行不可视。(脱离终端)

        3、设置工作目录(把此目录设置在根目录,为了保证工作目录一直存在)

        4、设置掩码(设置创建文件的掩码)

        5、对文件描述符重定向(将输入输出重定向到某个文件)

        6、开启自己的服务

1.3.3相关API分析

1.创建一个孤儿进程(为了脱离终端)

使用fork创建一个子进程之后,让父进程直接结束,子进程不要结束

2.设置会话id,创建一个新的会话。

(脱离目前终端,再在后台开一个新的终端)

#include <sys/types.h> 
#include <unistd.h> 
pid_t setsid(void); 
功能:创建一个新的会话,调用者会称为这个会话的组长 
参数: 空 
返回值:成功返回新的会话id,看不到这个终端,只知道新终端的id 失败返回(pid_t) -1 ,置位错误码

3.设置工作目录(为了保证工作目录一直存在)

把目录设置到了根目录,根目录一直存在,也是为了保证新开的终端一直存在。

#include <unistd.h> 
int chdir(const char *path); 
功能:改变进程的工作目录 
参数: path:新的工作目录 
返回值:成功返回0,失败返回-1,置位错误码

4.设置掩码(设置创建文件的掩码)

#include <sys/types.h> 
#include <sys/stat.h> 
mode_t umask(mode_t mask); 功能:设置进程创建文件的掩码 
参数: mask:新的掩码 
返回值:这个函数总是调用成功,返回之前的掩码数值

5.对文件描述符重定向(将输入输出重定向到某个文件)

像prinf,scanf等输入输出函数,都输出到终端,在终端输入,重定向到某个文件之后,输入输出的操作现象就在这个文件中显现了。

#include <unistd.h> 
int dup(int oldfd); 
功能:复制文件描述符,将oldfd复制产生一个新的fd并作为返回值返回 
参数: oldfd:旧的文件描述符 
返回值:成功返回复制出的新的文件描述符,失败返回-1,置位错误码 int dup2(int oldfd, int newfd); 
功能:复制oldfd生成新的newfd 
参数: oldfd:旧的文件描述符 newfd:新的文件描述符 
返回:成功返回复制出的新的文件描述符,失败返回-1,置位错误码

dup的使用

#include <my_head.h> 
int main(int argc, const char *argv[]) 
{ 
// 1.打开一个文件 int oldfd, newfd; oldfd = open("./a.txt", O_RDWR | O_CREAT, 0666); if (-1 == oldfd)PRINT_ERR("open error"); // 
//2.复制文件描述符 // newfd = dup(oldfd); // write(oldfd,"hello",strlen("hello")); // write(newfd," world",strlen(" world"));//都会写入a.txt文件中,oldfd,newfd代表的是同一个文件 close(1); // 关闭标准输出 newfd = dup(oldfd);//复制出的新的文件描述符遵循最小分配原则,由于标准输出1,被关掉了,所以复制出的新的文件描述符是1 printf("11111111111111111\n"); return 0; 
}

dup2使用实例

#include <my_head.h> 
int main(int argc, const char *argv[]) {// 1.打开一个文件 int oldfd, newfd; oldfd = open("./a.txt", O_RDWR | O_CREAT, 0666); if (-1 == oldfd) PRINT_ERR("open error"); newfd = 6; // //2.复制文件描述符 dup2(oldfd,newfd);//将oldfd复制,生成新的文件描述符6 write(oldfd,"hello",strlen("hello")); write(newfd," world",strlen(" world"));//都会写入a.txt文件中,oldfd,newfd代表的是同一个文件 dup2(oldfd,1);//复制出一个新的文件描述符1,旧的1(标准输出)会被关闭 printf("11111111111111111\n"); return 0; 
}

6.开启自己的服务

守护进程创建实例

注意:创建完成之后,看到现象了,九八创建的守护进程杀死

kill -9 进程pid

#include <my_head.h>int main(int argc,const char *argv[]){//1.创建一个孤儿进程pid_t ret;ret = fork();if(-1 == ret){PRINT_ERR("fork error");}else if(0 == ret){//子进程//2.设置会话setsid();//3.设置工作目录chdir("/");//4.设置掩码umask(0);//5.输入输出重定向//创建一个新的文件,作为日志文件int fd = open("/log.txt",O_RDWR|O_CREAT,0666);if(-1 == fd)PRINT_ERR("open log.txt error");//将输入输出重定向到log.txtdup2(fd,0);dup2(fd,1);dup2(fd,3);//开启自己的服务while(1){printf("hello world\n");fflush(NULL);sleep(1);}}else{//父进程exit(EXIT_SUCCESS);//父进程直接退出}return 0;
}

运行现象:


http://www.ppmy.cn/embedded/127687.html

相关文章

STT python

1. 安装所需库 我们需要安装这两个库&#xff0c;在命令行中运行以下命令&#xff1a; pip install SpeechRecognition pyaudio2. 使用 SpeechRecognition 库 SpeechRecognition 是一个 Python 库&#xff0c;用于将语音转换为文本&#xff0c;以下是一个简单的示例&#xf…

什么是联邦学习

想象一下&#xff0c;你有很多朋友&#xff0c;每个人手里都有一些自己的秘密&#xff08;数据&#xff09;&#xff0c;比如你的购物习惯、你的健身记录、你的阅读习惯等。这些秘密对你和你的朋友来说都很重要&#xff0c;你不想直接告诉其他人&#xff0c;但你又想从大家的信…

2024-10-14 商业分析-消费者权益维护和投诉相关-机械革命拒绝售后维修-记录

摘要: 考虑到商业环境基本都是各种坑蒙拐骗以次充好&#xff0c;在这个社会环境中&#xff0c;保护好自己的合法权益是重中之重。 拒不进行售后行为: 机械革命投诉电话通话录音记录资源-CSDN文库 3815862机械革命电脑检测报告(2).pdf资源-CSDN文库 消费者权益投诉平台: 一. 全…

vue中watch的用法

在 Vue.js 中&#xff0c;watch 是一个用于侦听和响应数据变化的选项。它常用于监听组件数据&#xff08;包括 props 和 data 中的值&#xff09;的变化&#xff0c;并在值发生变化时执行自定义逻辑。 基本用法 watch 选项接受一个对象&#xff0c;其中键是你想要侦听的变量&…

地图箭头方向检测系统源码分享

地图箭头方向检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

Docker exec bash -c 使用详解与 Python 封装示例

简介&#xff1a;docker exec 是 Docker 的一个实用命令&#xff0c;允许在正在运行的容器中执行命令。通过 bash -c 选项&#xff0c;可以执行复杂的命令串。 历史攻略&#xff1a; go&#xff1a;远程执行系统命令 Python&#xff1a;subprocess模块 Python-subprocess激…

【docker】mysql8.0 的 docker 安装

安装 指定mysql 的安装版本8.0.18 拉取镜像 docker pull mysql:8.0。18创建目录 mkdir -p /opt/docker_volumn/mysql/conf mkdir -p /opt/docker_volumn/mysql/log mkdir -p /opt/docker_volumn/mysql/data mkdir -p /opt/docker_volumn/mysql/mysql-files此步骤是为了将容…

【STM32 Blue Pill编程实例】-OLED显示DHT22传感器数据

OLED显示DHT22传感器数据 文章目录 OLED显示DHT22传感器数据1、DHT22介绍2、硬件准备与接线3、模块配置3.1 定时器配置3.2 DHT22引脚配置3.3 OLED配置4、代码实现在本文中,我们将介绍如何将 DHT22 温度和湿度传感器与 STM32 Blue Pill 开发板连接,并使用 HAL 库在 STM32CubeI…