Linux中进程管理(二)-学习笔记(四)

1、僵尸进程和孤儿进程
僵尸进程: 当子进程退出时,父进程没有收回子进程资源(PCB),则子进程变为僵尸进程。 
孤儿进程: 当父进程先于子进程结束,则子进程变为孤儿进程,子进程的父进程成为1号进程init进程,称为init进程,领养孤儿进程。
//程序1 清理僵尸进程(回收子进程)
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

//[root@localhost ~]# man 2 wait  <查看头文件>

int main(void)
{
    pid_t pid, pid_c;//定义pid,pid_c变量
    pid = fork();//调用1次,返回2次,在父进程中返回子进程ID号,在子进程中返回0
    if (pid>0)//父进程
    {
        while (1)
        {
            printf("I am the parent %d\n", getpid());//获取当前进程ID号
            //回收子进程
            //wait是一个阻塞函数,功能1-等待回收子进程资源,如果没有子进程,则返回-1
            //功能2-为父进程提供手段,知道子进程是怎么死的
            pid_c = wait(NULL);
            printf(" pid_c %d\n", pid_c);//获取当前进程ID号
            sleep(1);
        }
    }
    else if (pid == 0)//子进程
    {
        printf("I am child %d\n", getpid());//获取当前进程ID号
        sleep(10);//延时10s
    }
    else //进程创建出错
    {
        perror("fork\n");
        exit(-1);
    }
    return 0;
}

终端命令程序执行效果:

2、用fork创建子进程后执行的是和父进程相同的程序,但有可能执行不同的代码分支,子进程往往要调用一种exec函数以执行另一个程序。
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
注:调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
//程序2-1 子程序执行终端查看命令任务
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

//[root@localhost ~]# man 2 wait  查看头文件

int main(void)
{
    printf("hello\n");//输出hello
    execl("/bin/ls", "ls", "-l", NULL);//执行ls -l任务
    printf("world\n");//输出world
    return 0;
}

//程序2-2  另一种替换方式
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

//[root@localhost ~]# man 2 wait 查看头文件

int main(void)
{
    pid_t pid;//定义pid变量
    pid = fork();//调用1次,返回2次,在父进程中返回子进程ID号,在子进程中返回0
    char *argv[]={"ls","-l",NULL};//字符指针赋值
    if(pid > 0)//父进程
    {
        while (1)
        {
            printf("I am the parent %d\n", getpid());//获取当前进程ID号
            sleep(1);
        }
    }
    else if (pid == 0)//子进程
    {
        printf("I am child %d\n", getpid());//获取当前进程ID号
        execv("/bin/ls",argv);
    }
    else
    {
        perror("fork\n");
        exit(-1);
    }
    return 0;
}

终端命令程序执行效果:

//execl本意为去磁盘当中加载另一个可执行程序,用另一个程序段替换当前进程的代码段和数据段。(替换动作)
//程序3-1
#include <stdio.h>

int main(int argc,char *argv[])
{
    int i=0;
    while(i<argc)
    {
        printf("%s\n",argv[i++]);
    }
    return 8;
}

//程序3-2
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <sys/wait.h>//[root@localhost ~]# man 2 wait  查看头文件

int main(void)
{
    printf("hello\n");
    execl("/usr/lesson/dx1902/806/test1","./test1","xiaoxue","xiaomei","xiaoming",NULL);
    printf("world\n");
    return 0;
}

程序执行效果:

//程序4 打开浏览器
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

//[root@localhost ~]# man 2 wait  //查看头文件
//[root@localhost ~]# which firefox   --> /usr/bin/firefox

int main(void)
{
    pid_t pid;//定义pid变量
    pid = fork();//调用1次,返回2次,在父进程中返回子进程ID号,在子进程中返回0
    
    if(pid > 0)//父进程
    {
        while (1)
        {
            printf("I am the parent %d\n", getpid());//获取当前进程ID号
            sleep(1);//延时1s
        }
    }
    else if (pid == 0)//子进程
    {
        printf("I am child %d\n", getpid());//获取当前进程ID号
        //execl("/usr/bin/firefox","firefox","www.163.com",NULL);//法一
        execlp("firefox","firefox","www.163.com",NULL);//法二
    }
    else
    {
        perror("fork\n");
        exit(-1);
    }
    return 0;
}

//程序5 回收多个子进程
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

//[root@localhost ~]# man 2 wait  //查看头文件

int main(void)
{
    pid_t pid;//定义pid变量
    int n = 3;
    while (n--)
    {
        pid = fork();//调用1次,返回2次,在父进程中返回子进程ID号,在子进程中返回0
        if (pid == 0)
        {
            break;
        }
    }
    
    if (pid == 0)//子进程
    {
        printf("I am child %d\n", getpid());//获取当前进程ID号
        sleep(3);//延时3s
    }
    else if (pid > 0)//父进程
    {
        printf("n= %d\n", n);//获取当前进程ID号
        n++;
        pid_t pid_c;//定义pid_c变量
        while(1)
        {
            printf("I am the parent %d\n", getpid());//获取当前进程ID号
            pid_c=waitpid(0,NULL,WNOHANG);
            if (pid_c>0)
            {
                n++;
            }
            if (pid_c == -1)
            {
                continue;
            }
            else
            {
                printf("waite for the child %d\n", pid_c);
            }
            if (n == 3)
            {
                break;
            }
            sleep(1);
        }
    }
    else
    {
        perror("fork\n");
        exit(-1);
    }
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值