Linux系统与进程有关的系统调用
2021/11/21 7:12:53
本文主要是介绍Linux系统与进程有关的系统调用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
本文主要展示了如下系统调用的使用说明,并做了演示程序。
- getpid
- getppid
- fork
- waitpid
- exec
文章目录
- 一、进程相关的系统调用
- 1.查询进程的ID
- 2.创建进程
- 3.进程资源回收
- 4.进程退出
- 二、 exec()函数族
- 二、示例程序
- 1.示例程序1
- 2.示例程序2
一、进程相关的系统调用
1.查询进程的ID
-
getpid返回当前进程的pid,getppid则返回当前进程父进程的pid。
-
pid_t实质上是int类型
-
头文件以及函数声明如下:
#include <sys/types.h> #include <unistd.h> pid_t getpid(void); pid_t getppid(void);
2.创建进程
- 存在两个返回值。
- 在父进程中返回值大于0,返回子进程ID
- 在子进程中返回值等于零
- 如果创建失败,返回-1。
#include <sys/types.h> #include <unistd.h> pid_t fork(void);
- 父进程与子进程运行在分开的内存地址空间中,对数据的写操作不会互相影响。
Memory writes, file mappings (mmap(2)), and unmappings (munmap(2)) performed by one of the processes do not affect the other.
3.进程资源回收
这两个系统调用可以在子进程结束后回收子进程占用的全部资源,防止僵尸进程的产生。
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *wstatus);
- 调用wait函数的进程会被挂起(阻塞),直到其任意一个子进程结束。
- 当子进程结束时,该函数会回收子进程所占的资源(PCB等),并返回被回收的子进程的id。将被回收子进程的状态通过指针参数返回。
- 如果没有运行的子进程,则函数立刻返回-1.
对于waitpid函数,使用更为灵活
#include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t pid, int *wstatus, int options);
- 参数pid可以指定要回收的子进程的进程号id
- pid = -1: 表示要回收任意子进程
- pid = 0: 回收当前进程同一进程组中的任意一个进程
- pid > 0: 回收进程号为pid的子进程
- 参数options可以选择在回收时是否阻塞当前进程:
- 0: 阻塞(等价于wait)
- WNOHANG:不会阻塞,立即返回。
4.进程退出
#include <stdlib.h> void exit(int status);
二、 exec()函数族
exec()函数族会去在当前进程中调用另一个进程,执行新的进程的指令。
#include <unistd.h> extern char **environ; int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...);
- 调用失败才会有返回值,返回-1。
The exec() functions return only if an error has occurred. The return value is -1, and errno is set to indicate the error.
- 调用成功会使用新进程的指令覆盖当前进程,故当前进程剩余代码不执行。
- 因此一般是在子进程中使用。先使用fork创建子进程,在子进程中使用exec()函数族函数,从而使得子进程执行我们想要执行的可执行文件。
- excel()会执行path指定的可执行文件,但是excelp则会到环境变量下寻找file指定的可执行文件文件名。
二、示例程序
1.示例程序1
- 下面的程序,当前进程会创建五个子进程(注意break语句,是为了防止子进程创建新的进程)。
- 每一个子进程都会输出自身与父进程的进程号ip,之后进程结束。
- 当前进程在创建完五个子进程后,会进入死循环不断输出自身的进程号id。
#include <sys/types.h> #include <unistd.h> #include <stdio.h> int main() { pid_t pid; for(int i = 0; i < 5; i++){ pid = fork(); if(pid == 0){ break; } sleep(1); } if(pid > 0){ while(1){ printf("父进程,pid:%d\n", getpid()); sleep(1); } } else{ printf("子进程,pid:%d, ppid:%d\n", getpid(), getppid()); } return 0; }
- 可以预想到,子进程执行结束,其资源被释放,但是PCB等信息还保存着,于是五个子进程成为僵尸进程。占用进程号等系统资源。
- 程序输出如下图:
- 我们使用 ps -aux 命令,查看当前系统中的进程。
- 可以发现,创建的五个进程均成为僵尸进程。
- 于是启发我们,需要让主进程手动回收子进程资源。
2.示例程序2
- 在示例程序1的基础上,增加了waitpid系统调用,可以主动回收子进程。
- 在子进程执行的函数中加入了Sleep,为了让每一个子进程sleep的时间不同,使用进程号作为sleep的参数。
- 当子进程sleep结束后,父进程会使用不带阻塞的watpid系统调用回收资源并打印消息。
#include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t pid; for(int i = 0; i < 5; i++){ pid = fork(); if(pid == 0){ break; } sleep(1); } if(pid > 0){ while(1){ printf("父进程,pid:%d\n", getpid()); int ret = waitpid(-1, NULL, WNOHANG); if(ret > 0) printf("回收了进程%d\n", ret); sleep(1); } } else{ printf("子进程,pid:%d, ppid:%d\n", getpid(), getppid()); sleep(getpid() % 10 + 3); exit(0); } return 0; }
- 最终的结果如下图:
- 可以看出,waitpid是不会阻塞当前进程的。
这篇关于Linux系统与进程有关的系统调用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-12如何创建可引导的 ESXi USB 安装介质 (macOS, Linux, Windows)
- 2024-11-08linux的 vi编辑器中搜索关键字有哪些常用的命令和技巧?-icode9专业技术文章分享
- 2024-11-08在 Linux 的 vi 或 vim 编辑器中什么命令可以直接跳到文件的结尾?-icode9专业技术文章分享
- 2024-10-22原生鸿蒙操作系统HarmonyOS NEXT(HarmonyOS 5)正式发布
- 2024-10-18操作系统入门教程:新手必看的基本操作指南
- 2024-10-18初学者必看:操作系统入门全攻略
- 2024-10-17操作系统入门教程:轻松掌握操作系统基础知识
- 2024-09-11Linux部署Scrapy学习:入门级指南
- 2024-09-11Linux部署Scrapy:入门级指南
- 2024-08-21【Linux】分区向左扩容的方法