Liunx操作-Record13—进程控制相关函数的使用

目录

fork函数

获得当前进程:"pid_t getpid(void);"

获得当前进程父进程的id:"pid_t getppid(void);"

举例说明

查看进程相关信息的命令:"ps aux"

查看进程组相关信息的命令:"ps ajx"

杀死一个进程:"kill -9 id"

一个父进程创建n个子进程


fork函数

作用:创建一个新的进程

本来一个进程,通过fork函数,可以进行"分叉",变成了两个进程,比如,一个进程所创建的"a.out",通过fork函数进行分叉,一个还是自己本身(a.out),另一个是a.out的儿子,变成了两个进程。

再举一个例子,当执行指令的时候, 实际上也是调用了fork函数的,所以fork是linux实现的一个最基本的函数。

再接着讨论,如果是变成两个进程的话,那它的返回值该如何进行呢?那么按正常思路,如果fork失败了,就不返回值了,如果fork成功了,就返回两个返回值,父进程返回的是子进程的id;子进程返回 0(目的就是为了区分出谁是父进程,谁是子进程).

获得当前进程:"pid_t getpid(void);"

获得pid(进程id),获得当前进程的id号

获得当前进程父进程的id:"pid_t getppid(void);"

ppid,代指当前进程的父进程的id号

举例说明

编写一个函数:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    printf("Begin ....\n");
    pid_t pid = fork();
    printf("End ....\n");
    return 0;
}

运行结果如下: 

根据结果可以看出,"Begin"打印了一次,“End”打印了两次,可以知道,程序是在fork之后,开始分叉的(执行了两遍“    printf("End ....\n");”)。

接下来查看一下返回值,重新编写程序:

int main()
{
    printf("Begin ....\n");
    pid_t pid = fork();
    if(pid < 0){
        perror("fork err");
        exit(1);
    }
    if(pid == 0){
        //子进程
        printf("I am a child,pid = %d,ppid=%d\n",getpid(),getppid());
    }
    else if(pid > 0){
        //父进程的逻辑
        printf("childpid=%d,self=%d,ppid=%d\n",pid,getpid(),getppid());
    }
    printf("End ....\n");
    return 0;
}

运行如下: 

发现运行的结果显示,出现了一个孤儿进程,怎么算是孤儿进程呢?对比着上面的程序来进行分析:按照设想,当fork函数运行之后,就创建了一个父进程和一个子进程,那么应该逐一打印父子进程的id,都打印结束了,才可以打印“End”,但上面的运行结果是,当父进程的id打印完毕之后,就直接打印了“End”了,然后,又打印了一遍子进程的id,接着又打印了一遍"End",这是因为,当父进程打印完毕之后,就直接结束了,只剩下了子进程还在继续,那么子进程就成了所谓的孤儿进程,为了进行改进,不将子进程变成孤儿进程,就让父进程停留的时间加长,添加"sleep(1);":

    else if(pid > 0){
        //父进程的逻辑
        printf("childpid=%d,self=%d,ppid=%d\n",pid,getpid(),getppid());
		sleep(1);
    }

再次执行: 

这次的结果,就如我们所期了!

通过以上的代码实验,应该可以发现,相同一段代码,当出现fork函数时,开始进行"分叉",可以简单的理解成,代码自fork函数以下,新出来一个进程,从fork函数处开始运行,这个新出的进程,就叫做子进程;然后,原来的,仍然接着原来的顺序接着运行,这个进程就叫做父进程,只不过这两次执行是可以通过获得他们的ppid和id进行区分,那个是父进程,那个是子进程。

接着,对代码进行改造,在父子进程中,都加入一个新的while循环,来保证父子进程,都活着,

int main()
{
    printf("Begin ....\n");
    pid_t pid = fork();
    if(pid < 0){
        perror("fork err");
        exit(1);
    }
    if(pid == 0){
        //子进程
        printf("I am a child,pid = %d,ppid=%d\n",getpid(),getppid());
        while(1){
            printf("I am a child\n");
            sleep(1);
        }
    }
    else if(pid > 0){
        //父进程的逻辑
        printf("childpid=%d,self=%d,ppid=%d\n",pid,getpid(),getppid());
        while(1){
            sleep(1);
        }
    }
    printf("End ....\n");
    return 0;
}

查看进程相关信息的命令:"ps aux"

查看进程组相关信息的命令:"ps ajx"

可以追述进程之间的血缘关系,将上面代码执行后可知:

也可以反复追找,发现,许多程序都是其他程序的子进程,追根可以追溯到"init"进程,这个是所有程序的父进程,它创造了所有的进程。

杀死一个进程:"kill -9 id"

如果一个父进程和一个子进程都在运行,我杀死了父进程,子进程不会停止,而是被"init"领养,继续运行。

一个父进程创建n个子进程

比如,我现在想让一个父进程,创建出五个子进程,可设计程序如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    int n = 5;
    int i =0;
    pid_t pid = 0;
    for(i = 0; i < 5 ; i ++){//父进程循环结束
        pid = fork();
        if(pid == 0){
            //son 
            printf("I am child ,pid=%d,ppid=%d\n",getpid(),getppid());
            break;//子进程退出循环的接口
        }
        else if(pid > 0){
            //father 
            printf("I am father,pid=%d,ppid=%d\n",getpid(),getppid());
        }
    }
    while(1){
        sleep(1);
    }
    return 0;
}

运行如下:

就相当于把fork函数放到循环中不断运行,就不断生成子进程。需要注意的是,每次子进程启动后,就要接入一个子进程结束的接口"break",否则子进程就会继续衍生出新的子进程,而不是,只由父进程来衍生出子进程了。从操作系统来看,父子进程并没有区别,所以,如果父进程先结束了,那进程变成孤儿,进由"init"进程收养,还能继续运行;如果子进程先结束,对父进程没任何影响。

那么,尝试将上面代码进行改造,实现将上面的进程按(先创建先退出)顺序退出,父进程最后退出,那如何设计呢?

经过观察,可以知道,当进行第一次循环的时候,循环变量i的值依次是0,1,2,3,4。那么,可以让sleep的方式,来让第一个创建的子进程"睡的最少",第二个创建的子进程"睡的多点",第三个创建的子进程"睡的再多点"就行了。同时,通过i将父进程和子进程分两拨打印。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    int n = 5;
    int i =0;
    pid_t pid = 0;
    for(i = 0; i < 5 ; i ++){//父进程循环结束
        pid = fork();
        if(pid == 0){
            //son 
            printf("I am child ,pid=%d,ppid=%d\n",getpid(),getppid());
            break;//子进程退出循环的接口
        }else if(pid > 0){
            //father 
            printf("I am father,pid=%d,ppid=%d\n",getpid(),getppid());
        }
    }

    sleep(i);
    if(i < 5){
        printf("I am child ,will exit,pid=%d,ppid=%d\n",getpid(),getppid());
    }
    else{
        //father
        printf("I am parent,will out pid=%d,ppid=%d\n",getpid(),getppid());
    }

    return 0;
}

运行如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值