系统编程-进程初步2

进程初步2

目录

进程初步2

1、进程等待清理函数(wait)

2、等待指定的子进程(waitpid)

3、新的开辟进程的函数(vfork)

4、在程序中运行系统下的指令(system)

5、exec 函数族

例题:

tip1:特殊进程

0号进程

祖先进程

孤儿进程

僵尸进程

tip2:


1、进程等待清理函数(wait)

-- 函数头文件

  • #include <sys/types.h>
  • #include <sys/wait.h>

-- 函数原型

  • pid_t wait(int *wstatus);

-- 函数的作用:

  • 阻塞当前进程 等待子进程死亡

alt text

  • 子进程死亡 解除阻塞 并执行资源的回收

alt text

alt text

  • 获取子进程的退出状态

-- 函数的参数:

  • int *wstatus:用来接收子进程的退出状态
  • 子进程调用exit函数进行退出的参数会放到这里

alt text

  • 通过宏定义可以判断是否为正常退出
  • WIFEXITED(wstatus)
    -- 返回为真     进程为正常结束      如:exit、_exit、 main函数的return
    -- 返回为假      非正常结束    如:段错误、    kill 等
  • WEXITSTATUS(wstatus)
    -- 可以将子进程exit中的参数解出来

alt text

-- 函数的返回值:

  • 成功返回 死亡的子进程的进程号
  • 失败返回 -1

alt text

2、等待指定的子进程(waitpid)

-- wait函数等待的任意一个子进程,谁先死,先执行那个,而下面这个函数可以等待具体哪个进程。

  • pid_t waitpid(pid_t pid, int *wstatus, int options)

-- 函数的作用:

  • 根据参数的填写 进行相应的等待函数操作
  • 判断子进程的状态 是否死亡是否为正常退出
  • 获取子进程的返回值

-- 函数的参数:

  • pid:填写要进行等待的指定子进程进程号
  • -1:任意的一个子进程
  • ‘>0’:指定的子进程
  • wstatus:用来存放子进程的退出状态以及返回值
  • options:填写是否阻塞等待
  • 0:阻塞等待
  • WNOHANG:非阻塞

alt text

alt text

alt text

-- 函数的返回值:

  • 成功返回 死亡的子进程的进程号
  • 失败返回 -1

3、新的开辟进程的函数(vfork)

-- 函数的头文件

  • #include <sys/types.h>
  • #include <unistd.h>

-- 函数的原型

  • pid_t vfork(void);

-- 函数的作用:

  • 创建一个新的子进程并阻塞父进程
  • 子进程共用父进程的资源空间
  • 子进程退出之后 父进程开始运行
  • 运行顺序 子先父后

-- 函数的返回值:

  • 子进程中返回 0
  • 父进程中返回 子进程进程号

注:使用vfork子进程如果使用main函数中的return会出现段错误
我们需要在子进程中,使用_exit来进行退出 或者使用exec函数族来实现

alt text

alt text

4、在程序中运行系统下的指令(system)

-- 函数头文件

  • #include <stdlib.h>

-- 函数原型

  • int system(const char *command)

-- 函数的作用:

  • 运行系统下的指令

-- 函数的参数:

  • command:要运行的指令

alt text

-- 可以执行系统命令,主要原理是创建一个子进程,用exec函数族中的其中一个函数执行系统命令

-- 所以可以用fork函数和exec函数族中的函数写出来达到system函数的作用

5、exec 函数族

-- exec函数族中的函数功能效果是完全一样的,只是传参不同,所以只需要记住一个函数原型即可。

-- 主要用来执行系统下的指令 或者 程序

  • #include <unistd.h>

  • int execl(const char *pathname, const char arg, ... / (char *) NULL */);

  • int execlp(const char *file, const char arg, ... / (char *) NULL */);

  • int execle(const char *pathname, const char arg, ... /, (char *) NULL, char *const envp[] */);

  • int execv(const char *pathname, char *const argv[]);

  • int execvp(const char *file, char *const argv[]);

  • int execvpe(const char *file, char *const argv[], char *const envp[]);

-- 以上函数的作用:

  • 1 写在这些函数下面的内容就不会运行了 这些函数会将程序的原本内容进行替换
  • 2 他会获取新的空间资源 但是原本的进程号不变

-- int execl(const char *pathname, const char arg, ... / (char *) NULL */);

  • pathname:填写要运行的文件的绝对路径
  • arg:要运行的指令
  • arg1: 选项 和参数 等内容
  • 以 NULL 结尾

alt text

-- 并且在子进程中执行execl函数时,父进程是非阻塞的状态。

-- int execlp(const char *file, const char arg, ... / (char *) NULL */);

  • file:直接给指令名称
  • arg:指令
  • argx:参数和选项
  • 以 NULL 结尾
  • 例如:execlp("ls","ls","-l",NULL);

-- int execv(const char *pathname, char *const argv[]);

  • pathname:指令所在的绝对路径
  • argv:指向运行的内容
  • char * a[] = {"ls","-l",NULL};
  • execv("/bin/ls",a);

例题:

-- 实现自动循环播放音乐

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

#include <stdio.h>

//实现自动循环播放音乐

int main(int argc, char const *argv[])
{
    int n=0;
    
    while(1){
    n++;
    pid_t pid = vfork();
    if(pid == 0){   //子进程
        printf("Im son\n");
        switch(n)
        {
            case 1:execl("/bin/mpg123","mpg123","/home/pimouren/learn/系统编程/5 进程初步/music/benxi.mp3",NULL);
            
            break;
            case 2:execl("/bin/mpg123","mpg123","/home/pimouren/learn/系统编程/5 进程初步/music/daoxiang.mp3",NULL);
            
            
            break;
            case 3:execl("/bin/mpg123","mpg123","/home/pimouren/learn/系统编程/5 进程初步/music/苏打绿 - 小情歌.mp3.mp3",NULL);
            break;
            default:n=0;break;

        }
    
    }else if(pid > 0)   // 父进程
    {

        printf("**********\n");
        pid_t a = wait(NULL);
        if(a == pid)
        {
            printf("音乐播放完毕,开启下一首\n");
        }
    }
    }
    
    return 0;
}

tip1:特殊进程

0号进程
  • 操作系统的引导程序
祖先进程
  • 操作系统启动的第一个程序,1号进程
孤儿进程
  • 父进程先退出,子进程被init接管,子进程退出后init会回收其占用的相关资源

  • 缺点:子进程的相关资源无法清理回收

僵尸进程
  • 子进程先退出,父进程没有回收子进程的资源,导致子进程无法回收

-- 一种非常特殊的进程,它几乎已经放弃了所有内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间

tip2:

-- pstree 命令可以用来查看进程树,包括所有的子进程。它以树形结构显示当前系统中的进程及其父子关系,使得理解进程间的层级关系变得更加直观。

使用方法很简单,只需在终端中输入 pstree 命令即可。
-- 如果你想查看特定用户的进程树,可以使用 -u 选项,例如:

  • pstree -u 用户名

-- 此外,你也可以使用 -p 选项来显示进程的 PID(进程ID):

  • pstree -p

-- 如果你只想查看某个特定进程及其子进程,可以在命令后面加上该进程的 PID,例如:

  • pstree -p 1234
    -- 这将显示 PID 为 1234 的进程及其子进程的树形结构。
  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值