3.进程
一.fork()
fork()用来创建一个子进程,子进程复制父进程的0-3G空间和父进程内核中的PCB,但子进程和父进程的id号不同。
fork()调用一次,返回两次
在父进程中返回子进程的PID,在子进程中返回0。
例:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { pid_t pid; pid = fork(); if (pid > 0) { printf("cur process is parent\n"); printf("cur pid is: %d\n", getpid()); printf("cur parent pid is: %d\n", getppid()); while(1); } else if (pid == 0) { printf("cur process is child\n"); printf("cur pid is: %d\n", getpid()); printf("cur parent pid is: %d\n", getppid()); while(1); } else { perror("fork"); } return 0; }
运行结果:
cur process is parent
cur pid is: 5924
cur parent pid is: 2736
cur process is child
cur pid is: 5925
cur parent pid is: 5924
二.execl()&execv()&execle()&execve()&execlp()&execvp()
char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL}; char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL}; execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL); execv("/bin/ps", ps_argv); execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp); execve("/bin/ps", ps_argv, ps_envp); execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL); execvp("ps", ps_argv);
PS:
1.只有execve是真正的系统调用,其它五个函数最终都调用execve
2.由于exec函数只有错误返回值,只要返回了一定是出错了,所以不需要判断它的
返回值,直接在后面调用perror即可
例:
#include <unistd.h> #include <stdlib.h> int main() { // execl("/bin/ls", "ls", "-l", NULL); char *const ps_argv[] = {"ps", "aux", NULL}; //execvp("ps", ps_argv); execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL); perror("exec ps"); exit(1); return 0; }
运行结果:
PID PPID PGRP SESS TPGID COMMAND
2699 2693 2699 2699 3926 bash
3926 2699 3926 2699 3926 ps
三.wait()&waitpid()
◆ wait()
僵尸进程: 子进程退出,父进程没有回收子进程资源(PCB),则子进程变成僵尸进程(Z+)(当子进程运行结束后,其用户空间已被释放,但它的PCB没有被立即释放,等待父进程将其释放)
孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为1号进程init进程,称为init进程领养孤儿进程
可使用wait()函数除去僵尸进程
PS:
1.wait()函数是一个阻塞函数,等待回收子进程资源,如果没有子进程,wait返回-1
2.waitpid()函数则是一个非阻塞函数
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> int main() { pid_t pid; pid = fork(); if (pid > 0) { while (1) { printf("I am parent process\n"); printf("wait for child: %d\n", wait(NULL)); sleep(1); } } else if (pid ==0) { printf("I am child process\n"); printf("My pid is: %d\n", getpid()); sleep(10); } else { perror("fork"); } return 0; }
运行结果:
I am parent process
I am child process
My pid is: 5308
wait for child: 5308
I am parent process
wait for child: -1
I am parent process
wait for child: -1
I am parent process
wait for child: -1
I am parent process
wait for child: -1
I am parent process
wait for child: -1
I am parent process
wait for child: -1
◆ waitpid()
pid_t waitpid(pid_t pid, int *status, int options);
< -1 回收指定进程组内的任意子进程
-1 回收任意子进程
0 回收和当前调用waitpid一个组的所有子进程
> 0 回收指定ID的子进程
WNOHANG 如果没有子进程退出立即返回,这样就实现了非阻塞的wait
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> int main() { pid_t pid; pid = fork(); if (pid > 0) { while (1) { printf("I am parent process\n"); pid_t pid_c = waitpid(0, NULL, WNOHANG); printf("go to next...\n"); } } else if (pid == 0) { printf("I am child process\n"); sleep(10); } else { perror("fork"); } return 0; }
运行结果:
I am parent process
go to next...
I am parent process
go to next...
I am parent process
go to next...
I am parent process
go to next...
I am parent process
go to next...
I am parent process
go to next...
I am parent process
go to next...
I am parent process
go to next...
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2016-11-24 新浪微博客户端(37)-发布新微博
2016-11-24 新浪微博客户端(36)-自定义带placeholder的TextView
2016-11-24 iOS-开启arc之后 NSNotificationCenter removeObserver 是否需要调用
2016-11-24 新浪微博客户端(35)-使用NSMutableAttributedString实现多行文本的效果
2016-11-24 android-android获取navigationview 上的控件id