【Linux-14】进程信号(下)

本文详细介绍了Linux中的进程概念,包括并发与并行的区别,进程控制块PCB的内容。重点讲解了fork和vfork函数的使用,以及它们如何在内核中通过clone函数创建进程。此外,还阐述了wait函数在处理子进程退出和防止僵尸进程中的重要作用。最后提到了popen和system函数与fork的区别。
愿我们都能成为
一个童心未泯的大人,不被世俗化,不被规则化~

目录:

  • 每日总结
  • 掌握fork/vfork函数的使用
  • 熟练掌握wait的函数使用
  • popen/system两个函数和fork的区别

>>1.每日总结

1.程序和进程

程序:二进制文件,占用的磁盘空间

进程:启动的程序;所有的数据都在内存中;需要占用更多的系统资源;(cpu,物理内存)

2.并发和并行

并发:时间段的概念。

并行:增加处理器并行处理。(例如:淘宝,12306购票)

3.pcb:进程控制块

  • 进程id。系统中每个唯一的id,在C语言中用pid_t 类型的表示,其实就是一个非负整数;
  • 进程的状态:就绪,运行,挂起,停止等;
  • 进程切换时需要保存和恢复的一些CPU寄存器;
  • 描述虚拟地址空间的信息;
  • 描述控制终端的信息;
  • umask掩码;
  • 文件描述符,包含很多指向file结构体指针;
  • 用户id和组id;
  • 多个进程形成进程组;

>>2.fork/vfork函数及其实现

  • 相似Linux中fork函数是非常重要的,它从已经存在的进程中创建一个新进程。新进程为子进程,而原进程为父进程;
  • fork函数:通过复制调用进程创建一个新的子进程;
  • fork函数的返回值:子进程返回1;父进程返回的是子进程的pid;
  • vfork函数:创建子进程,与父进程共用同一个虚拟地址空间;
  • fork/vfork函数在内核中创建进程都是调用clone函数实现pcb创建并拷贝数据的。

结果演示:

 >>wait函数的实现(进程等待)

  • 子进程退出,父进程如果不管不顾,就可能造成“僵尸进程”的问题,进而造成内存泄漏;
  • 进程一旦成为“僵尸进程”,那么就“刀枪不入”,就连kill -9也无能为力,没有办法杀死一个已经死去的进程
  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出的信息。
  • wait函数的返回值:成功返回被等待的进程pid;失败返回-1;
  • wait函数参数:输出类型参数,获取子进程退出状态,不关心则可以设置为NULL。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>

int main()
{
    int pid = fork();
    if (pid < 0) {
        //errno是一个全局变量,存储每次系统调用出现错误原因编号
        //strerror,通过错误编号获取字符串错误原因
        printf("fork error :%s\n", strerror(errno));
        //perror直接打印上一个系统调用错误原因
        perror("fork error");
    }else if(pid == 0) {
        sleep(3);
        exit(257);
    }
    //pid_t wait(int *status);
    //阻塞等待任意一个子进程退出,获取返回值
    //wait(NULL);
    
    //pid_t waitpid(pid_t pid, int *status, int options);
    //阻塞等待任意一个子进程或者指定的子进程退出
    //pid:  -1:等待任意一个子进程   pid>0:等待指定子进程
    //options:  WNOHANG:将waitpid设置为非阻塞 0:默认阻塞
    //返回值:若WNOHANG被指定,没有子进程退出则立即报错返回0;错误:-1
    int statu;
    while(waitpid(-1, &statu, WNOHANG) == 0) {
        //非阻塞轮询操作
        printf("drink coffee\n");
        sleep(1);
    }
    if ((statu & 0x7f) == 0){
        printf("exit code:%d\n", (statu >> 8) & 0xff);
    }
    if (WIFEXITED(statu)) {
        printf("exit code:%d\n", WEXITSTATUS(statu));
    }

    while(1) {
        printf("i am parent\n");
        sleep(1);
    }
    return 0;
}

结果演示:

>>popen/system

system:在执行期间调用进程会一直等待shell命令执行完成
popen:无须等待shell命令执行完成就返回   (并行执行)
popen后需要调用pclose防止子进程变成”僵尸”状态。 

fork :执行期间父进程等待子进程的退出码

system:对SIGCHLD、SIGINT、SIGQUIT都做了处理,
    system()调用堆信号屏蔽的原因是因为system能够及时的退出
    并且能够正确的获取子进程的退出状态(成功回收子进程)。 

popen:没有对信号做任何的处理。
    popen()函数中没有屏蔽SIGINT、SIGQUIT的原因
    是因为popen是”并行的”,不能影响其它”并行”进程。
system:执行shell命令最后返回是否执行成功,
popen:执行命令并且通过管道和shell命令进行通信。

在特权(setuid、setgid)进程中千万注意不要使用system和popen这两个函数!

 

 

 

 

 

~bye

~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值