10.2 Linux_进程_进程相关函数

devtools/2024/10/18 9:06:08/

创建子进程

函数声明如下:

pid_t fork(void);

返回值:失败返回-1,成功返回两次,子进程获得0(系统分配),父进程获得子进程的pid

注意:fork创建子进程,实际上就是将父进程复制一遍作为子进程,但子进程只执行fork之后的代码,不执行fork之前的代码。这里的"复制"代表了父子进程的空间是独立的,互不影响。

孤儿进程与僵尸进程:

如果父进程先结束,那么子进程变成孤儿进程,最终被init进程收养,并且子进程变为后台进程。

如果子进程先结束,但父进程没有回收子进程,那么子进程变成僵尸进程。

fork基本使用方法:

pid = fork();
if(pid<0){perror("fork");return -1;
}else if(pid == 0){//子进程代码
}else if(pid > 0){//父进程代码
}

创建多个子进程: 

具体代码实现如下:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>int main(){pid_t pid;int i;printf("father pid = %d\n",getpid());for(i=0;i<5;i++){if((pid=fork()) < 0){perror("fork");return -1;}else if(pid == 0){break;//子进程不进行fork}}if(i==5){printf("father pid = %d\n",getpid());}else{printf("child pid = %d\n",getpid());}while(1);return 0;
}

代码执行结果如下: 

进程结束

函数声明如下:

void exit(int status);void _exit(int status);
void _Exit(int status);

exit结束进程后,会刷新缓冲区,其余这三个函数没有区别。

status:返回给系统的状态值

注意:main函数结束会隐式调用exit函数,所以在main函数结束时会刷新缓冲区。

exit刷新缓冲区实验:

进程回收

函数声明如下:

pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);

返回值:成功返回回收的子进程的pid,失败返回EOF

wstatus:保存子进程结束的状态,NULL代表直接释放子进程的PCB,不接收返回值。

pid:想要回收的子进程的pid,-1代表任意子进程,0代表进程组中的任意子进程

options:回收的方式

  • 0:阻塞等待子进程结束
  • WNOHANG:不阻塞等待子进程结束,子进程未结束也返回,继续执行下面代码。

注意:父进程调用该函数后一直处于阻塞状态,直到子进程结束

通过宏来解析wstatus:

wstatus中包含了是否正常退出、exit返回值、是否被信号结束、结束进程的信号类型。

解析的宏如下:

含义
WIFEXITED(wstatus)判断子进程是否正常退出
WEXITSTATUS(wstatus)获取子进程返回值,即:exit的值
WIFSIGNALED(wstatus)判断子进程是否被信号结束
WTERMSIG(wstatus)获取结束子进程的信号类型

wait测试代码:

具体代码实现如下:

#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int main(){pid_t pid;int wstatus;if((pid = fork()) < 0){return -1;}else if(pid == 0){sleep(10);printf("now child exit\n");exit(2);}else{wait(&wstatus);//以阻塞方式等待子进程退出printf("是否正常退出:%d\n",WIFEXITED(wstatus));printf("子进程的返回值为%d\n",WEXITSTATUS(wstatus));printf("子进程是否被信号结束%d\n",WIFSIGNALED(wstatus));printf("结束子进程的信号类型%d\n",WTERMSIG(wstatus));}return 0;
}

代码执行结果如下:

waitpid填写WNOHANG实验:

当子进程退出后,子进程的pid会一直存在,直到被回收。当写入WNOHANG时,waitpid不会进入阻塞。但可以通过循环的模式,一次次判断是否有子进程需要回收。

具体代码实现如下:

#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int main(){pid_t pid;int wstatus;if((pid = fork()) < 0){return -1;}else if(pid == 0){sleep(5);printf("now child exit\n");exit(2);}else{while(1){if(waitpid(pid,&wstatus,WNOHANG) > 0){ //当子进程退出后,父进程退出whilebreak;}printf("father is running\n");sleep(1);}}return 0;
}

代码执行结果如下:

进程执行其他程序

1、exec

exec函数的作用:

进程调用exec函数执行某个程序,调用后进程的当前内容被指定的程序替换,但进程号不变。

利用exec可以实现父子进程执行不同的程序:创建子进程->子进程调用exec执行其他功能。 

函数声明如下:

int execl(const char *pathname, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);

返回值:失败返回-1

pathname:执行程序的路径

file:执行程序的名字,会从环境变量PATH中寻找该执行程序

arg:执行程序的参数,第0个参数为程序名

argv:执行程序的参数,以字符串数组形式呈现

...:写NULL、0、(char*)0,这三个中的其中一个

示例:使用execl实现 " ls -li . " 的功能

具体代码实现如下:

#include <unistd.h>
#include <stdio.h>int main(){//ls -li . 有三个参数,ls是第0个参数execl("/bin/ls","ls","-li",".",NULL);printf("get\n");return 0;
}

代码运行结果如下:

示例:使用execv实现 " ls -li . " 的功能

具体代码实现如下:

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main(){//这里最后一个NULL,不需要加双引号char* a[] = {"ls","-li",".",NULL};if(execv("/bin/ls",a) == -1){perror("execv");}printf("get\n");return 0;
}

代码运行与execl一样

2、system

system的作用:

执行一个指令,调用system后会等待指令执行结束,之后继续执行下面的代码,而不是像exec那样下面的代码被替代。

函数声明如下:

int system(const char *command);

返回值:失败返回EOF

command:一个指令,以字符串形式呈现

示例:使用system实现 " ls -li . " 的功能

具体代码实现如下:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int main(){system("ls -li .");printf("get\n");return 0;
}

代码运行结果如下: 


http://www.ppmy.cn/devtools/122988.html

相关文章

【Linux】动态库和静态库

一、什么是动态库和静态库 静态库&#xff08;.a&#xff09;&#xff1a;程序在编译链接的时候将库的代码连接到可执行文件中&#xff0c;程序运行的时候将不再需要静态库。动态库&#xff08;.so&#xff09;&#xff1a;程序在运行的时候才会去连接动态库中的代码&#xff…

LeetCode 121. 买卖股票的最佳时机

LeetCode 121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你…

Caffeine Cache基础入门

Caffeine Cache基础入门 Caffeine Cache 以其高性能和可扩展性赢得「 本地缓存之王 」的称号&#xff0c;它是一个 Java 缓存库。 Spring Boot 1.x 版本中的默认本地缓存是 Guava Cache。但在 Spring5 &#xff08;SpringBoot 2.x&#xff09;后&#xff0c;Spring 官方放弃了…

Golang | Leetcode Golang题解之第451题根据字符出现频率排序

题目&#xff1a; 题解&#xff1a; func frequencySort(s string) string {cnt : map[byte]int{}maxFreq : 0for i : range s {cnt[s[i]]maxFreq max(maxFreq, cnt[s[i]])}buckets : make([][]byte, maxFreq1)for ch, c : range cnt {buckets[c] append(buckets[c], ch)}an…

无人机视角垃圾检测数据集,26700余张无人机图像,超过4万标注信息,共3.6GB数据量,可用于环卫快速检查,垃圾快速定位等应用。

无人机视角垃圾检测&#xff0c;26700余张无人机图像&#xff0c;超过4万标注信息&#xff0c;共3.6GB数据量&#xff0c;可用于环卫快速检查&#xff0c;垃圾快速定位等应用。 名称 无人机视角垃圾检测数据集 规模 图像数量&#xff1a;26700余张标注信息&#xff1a;超过4…

HT338 2x50W D类立体声音频功放

1 特性 ● 输出功率(BTL) 2x40W (VDD18V,RL4Ω, THDN10%) 2x50W(VDD24V.RL6Ω,THDN10%) 2x40W(VDD24V,RL8Ω, THDN10%) ● 输出功率(PBTL模式) 80W(VDD24V,RL4Ω,THDN10%) 100W(VDD24VRL3Ω,THDN10%) ● 单电源系统&#xff0c;4.5V-26V宽电压输入范围 ● 超过90%效率&#xf…

上海交通大学《2022年+2023年816自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《上海交通大学816自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2022年真题 2023年真题 Part1&#xff1a;2022年2023年完整版真题 2022年真题 2023年…

全网都在找的Python生成器竟然在这里!简单几步,让你的代码更简洁、更高效!

博客主页&#xff1a;长风清留扬-CSDN博客系列专栏&#xff1a;Python基础专栏每天更新大数据相关方面的技术&#xff0c;分享自己的实战工作经验和学习总结&#xff0c;尽量帮助大家解决更多问题和学习更多新知识&#xff0c;欢迎评论区分享自己的看法感谢大家点赞&#x1f44…