ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux系统与进程有关的系统调用

2021-11-20 13:58:51  阅读:119  来源: 互联网

标签:调用 int 系统 pid 回收 sleep Linux 进程 include


本文主要展示了如下系统调用的使用说明,并做了演示程序。

  • getpid
  • getppid
  • fork
  • waitpid
  • exec

文章目录

一、进程相关的系统调用

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是不会阻塞当前进程的。

标签:调用,int,系统,pid,回收,sleep,Linux,进程,include
来源: https://blog.csdn.net/m0_54002804/article/details/121438461

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有