Linux进程相关 创建与回收

进程

目标

  • 掌握fork/getpid/getpid/getppid函数的使用
  • 熟练掌握ps/kill命令的使用
  • 熟练掌握execl/execlp函数的使用
  • 说出什么时僵尸进程 什么是孤儿进程
  • 熟练掌握wait函数的使用
  • 熟练掌握waitpid函数的使用

程序相关概念

什么是程序 ?

编译好的二进制文件 .

什么是进程 ?

运行着的程序. 站在程序员的角度,运行一系列指令的过程. 站在系统角度分配好资源的基本单位.

区别

  • 程序占用磁盘,不占用系统资源

  • 内存占用系统资源

  • 一个程序对应多个进程,一个进程对应一个程序.

  • 程序没有生命周期,进程有生命周期.

进程相关函数

fork 创建进程

#include <unistd.h>

pid_t fork(void);

返回值

  • 失败返回-1

  • 成功两次返回

    • 父亲进程返回 子进程id
    • 子进程返回0

getpid获取进程id / getppid获取父进程id

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

pid_t getpid(void);		
pid_t getppid(void);

实例

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

int main()
{
    pid_t id = getpid();

    printf("当前进程的id为:%d\n",id);

    printf("开始创建进程\n");
    pid_t id1 = fork();
    if(id1<0){
        perror("fork err");
        return -1;
    }
    printf("\n创建进程结束\n");
    if(id1 == 0)
    {
        
        printf("我是子进程:%d\n",getpid());
        pid_t id2 = getppid();
        printf("我的父进程:%d\n",id2);
        return 0;
    }
    
    printf("我是父进程:%d\n",id);
    printf("我的子进程:%d\n",id1);


    return 0;
}

子进程打印时发现父进程的id为1 因为父进程先死了.

查看进程

ps aux

ps ajx

杀死进程

kill -9 进程id

进程共享

父子进程之间在fork后.有哪些相同不同之处?

刚fork后:

  • 父子相同之处:全局变量, data, text, 堆, 栈, 环境变量, 用户id, 宿主目录, 进程工作目录, 信号处理函数…
  • 父子不同之处:
    1. 进程ID
    2. fork() 返回值
    3. 进程运行时间
    4. 闹钟(定时器)
    5. 未决信号集

似乎子进程复制了父进程0-3G的用户空间, 以及父进程的PCB, 但pid不同. 真的每一个子进程都复制了一份父进程的地址空间?

当然不是, 父子进程遵循读时共享,写时复制的原则. 这样无论执行子进程还是父进程的逻辑都能节省空间开销.

测试,父子进程是否共享变量.

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

int main()
{
    int a = 100;
    pid_t pid  = fork();
    if(pid < 0)
    {
        printf("创建子进程失败\n");
        return 0;
    }
    if(pid == 0)
    {
        printf("子进程a 的地址%p\n",&a);
    }
    else
    {
        printf("父进程a 的地址%p\n",&a);
        sleep(1);
    }

}

exec族函数

#include <unistd.h>

extern char **environ;

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);

实例

#include<unistd.h>

int main()
{
    // execl("ls","ls","-l","--color=auto",NULL);
    execlp("/bin/ls","ls","-l","--color=auto",NULL);
    perror("");
    return 0;
}

孤儿进程和僵尸进程

孤儿进程: 父进程死了,子进程被init进程领养.

僵尸进程: 子进程死了,父进程没有回收资源(PCB)

如何回收僵尸进程: 杀死父亲,init 进程领养,负责回收.

回收进程

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

pid_t wait(int *status);

pid_t waitpid(pid_t pid, int *status, int options);

int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

wait

作用: 阻塞等待 回收子进程资源 查看死亡原因

wait

  • 成功返回终止的子进程ID
  • 失败返回-1

waitpid

  • pid
    • <-1 -组id
    • -1 回收任意
    • 0 回收和调用进程id相同组内的子进程
    • >0 回收指定的pid
  • options
    • 0与wait相同,也会阻塞
    • WNOHANG 如果当前没有子进程退出,会立刻返回

查看死亡原因

  • 正常死亡: WIFEXITED(status)

    如果正常死亡 WIFEXITED为真,WEXITSTATUS(status)得到退出状态

  • 非正常死亡 WIFSIGNALED(status)

    WIFSIGNALED为真WTERMSIG(status)得到第几号信号将其杀死的.

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

int main()
{
    pid_t pid = fork();
    if(pid == 0)
    {
        printf("I am child, will die!\n");
        sleep(2);
        // return 102;
        exit(103);
    }
    else if(pid >0)
    {
        printf("I am parent, wait for child die\n");
        int status;

        pid_t wpid = wait(&status);
        printf("wait ok, wpid = %d, pid = %d\n",wpid,pid);
        if(WIFEXITED(status)){
            printf("child exit with %d\n",WEXITSTATUS(status));
        }
        if(WIFSIGNALED(status)){
            printf("child exit with %d\n",WTERMSIG(status));
        }
    }

    return 0;
}

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

去留意

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值