Linux你必须知道的小知识-8

80 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

2.25 请你说说Linux的fork的作用

参考回答

fork函数用来创建一个子进程。对于父进程,fork()函数返回新创建的子进程的PID。对于子进程,fork()函数调用成功会返回0。如果创建出错,fork()函数返回-1。

答案解析

fork()函数,其原型如下:

#include <unistd.h>  
pid_t fork(void);  

fork()函数不需要参数,返回值是一个进程标识符PID。返回值有以下三种情况:

(1) 对于父进程,fork()函数返回新创建的子进程的PID。
(2) 对于子进程,fork()函数调用成功会返回0。
(3) 如果创建出错,fork()函数返回-1。

fork()函数创建一个新进程后,会为这个新进程分配进程空间,将父进程的进程空间中的内容复制到子进程的进程空间中,包括父进程的数据段和堆栈段,并且和父进程共享代码段。这时候,子进程和父进程一模一样,都接受系统的调度。因为两个进程都停留在fork()函数中,最后fork()函数会返回两次,一次在父进程中返回,一次在子进程中返回,两次返回的值不一样,如上面的三种情况。

2.26 请你说说什么是孤儿进程,什么是僵尸进程,如何解决僵尸进程

参考回答

  1. 孤儿进程:是指一个父进程退出后,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并且由init进程对它们完整状态收集工作。

  2. 僵尸进程:是指一个进程使用fork函数创建子进程,如果子进程退出,而父进程并没有调用wait()或者waitpid()系统调用取得子进程的终止状态,那么子进程的进程描述符仍然保存在系统中,占用系统资源,这种进程称为僵尸进程。

  3. 如何解决僵尸进程

    (1)一般,为了防止产生僵尸进程,在fork子进程之后我们都要及时使用wait系统调用;同时,当子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵尸进程的目的。

    (2)使用kill命令

    ​ 打开终端并输入下面命令:

        ps aux | grep Z
    

    ​ 会列出进程表中所有僵尸进程的详细内容。

    ​ 然后输入命令:

        kill -s SIGCHLD pid(父进程pid)
    

2.27 请你说说什么是守护进程,如何实现?

参考回答

  1. 守护进程:守护进程是运行在后台的一种生存期长的特殊进程。它独立于控制终端,处理一些系统级别任务。

  2. 如何实现

    (1)创建子进程,终止父进程。方法是调用fork() 产生一个子进程,然后使父进程退出。

    (2)调用setsid() 创建一个新会话。

    (3)将当前目录更改为根目录。使用fork() 创建的子进程也继承了父进程的当前工作目录。

    (4)重设文件权限掩码。文件权限掩码是指屏蔽掉文件权限中的对应位。

    (5)关闭不再需要的文件描述符。子进程从父进程继承打开的文件描述符。

答案解析

实现代码如下:

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

#define MAXFILE 65535  

int main(){  
    //第一步:创建进程   
    int pid = fork();  
    if (pid > 0)  
        exit(0);//结束父进程   
    else if (pid < 0){  
        printf("fork error!\n");  
        exit(1);//fork失败,退出   
    }  
    //第二步:子进程成为新的会话组长和进程组长,并与控制终端分离   
       setsid();  
    //第三步:改变工作目录到  
    chdir("/");  
    //第四步:重设文件创建掩模   
    umask(0);  
    //第五步:关闭打开的文件描述符  
    for (int i=0; i<MAXFILE; ++i)   
        close(i); 
        sleep(2);  
    }  
    return 0;  
}