美文网首页
Linux多进程

Linux多进程

作者: 锈色的栅栏 | 来源:发表于2024-11-07 14:59 被阅读0次

1【进程号PID】

每个进程都由一个进程号来标识,其类型为 pid_t(整型),进程号的范围:0~32767。进程号总是唯一的,但进程号可以重用。当一个进程终止后,其进程号就可以再次使用.
进程号(PID): 标识进程的一个非负整型数
父进程号(PPID):父进程号
进程组号(PGID): 进程组是一个或多个进程的集合。

1、获取进程号的函数

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);

功能:
    获取本进程号(PID)
参数:
    无
返回值:
    本进程号

2、获取父进程的ID

#include <sys/types.h>
#include <unistd.h>
pid_t getppid(void);

功能:
    获取调用此函数的进程的父进程号(PPID)
参数:
    无
返回值:
    调用此函数的进程的父进程号(PPID)

3、获取进程组的ID

#include<sys/types.h>
#include<unistd.h>
pid_t getpgid(pid_t pid);

功能:
    获取进程组号(PGID)
参数:
    pid:进程号
返回值:
    参数为 0 时返回当前进程组号,否则返回参数指定的进程的进程组号

2【创建进程fork】

1、fork函数

系统允许一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构模型.

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

功能:
    用于从一个已存在的进程中创建一个新进程,新进程称为子进程,原进程称为父进程。
参数:
    无
返回值:
    成功:子进程中返回 0,父进程中返回子进程 ID。pid_t,为整型。失败:返回-1。
           失败的两个主要原因是:
           1)当前的进程数已经达到了系统规定的上限,这时 errno 的值被设置为 EAGAIN。
            2)系统内存不足,这时 errno 的值被设置为 ENOMEM

2、fork出来的子进程和父进程之间的关系

使用fork函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间。使用fork函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间。 地址空间: 包括进程上下文、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。 子进程所独有的只有它的进程号,计时器等。因此,使用fork函数的代价是很大的.

3【特殊的进程】

1、孤儿进程(无危害)
父进程先结束、子进程就是孤儿进程,会被1号进程接管(1号进程负责给子进程回收资源)
2、僵尸进程(有害)
子进程结束,父进程没有回收子进程资源(PCB),子进程就是僵尸进程。
3、守护进程
守护进程 是脱离终端的 孤儿进程。在后台运行。为特殊服务存在的。(一般用于服务器)

4【父进程回收子进程的资源】

在每个进程退出的时候,内核释放该进程所有的资源、包括打开的文件、占用的内存等。但是仍然为其保留一定的信息,这些信息主要主要指进程控制块PCB的信息(包括进程号、退出状态、运行时间等)
父进程可以通过调用wait或waitpid得到它的退出状态同时彻底清除掉这个进程。注意:一次wait或waitpid调用只能清理一个子进程,清理多个子进程应使用循环。wait、waitpid基本上都是在父进程调用

1、wait函数

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status);

功能:
    等待任意一个子进程结束,如果任意一个子进程结束了,此函数会回收该子进程的资源。
参数:
        status : 进程退出时的状态信息。
返回值:
        成功:已经结束子进程的进程号 失败: -1
        注意:
            wait阻塞若调用进程没有子进程,该函数立即返回子进程已经结束,该函数同样会立即返回,
            并且会回收那个早已结束进程的资源
状态值:
    WIFEXITED(status) 如果子进程是正常终止的,取出的字段值非零。
    WEXITSTATUS(status) 返回子进程的退出状态,退出状态保存在status变量的8~16位

2、waitpid函数

#include<sys/types.h>
#include<sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options);

功能:
      等待子进程终止,如果子进程终止了,此函数会回收子进程的资源。
参数:
        pid : 参数 pid 的值有以下几种类型:
            pid>0 等待进程ID等于pid的子进程。
            pid = 0 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid 不会等
            待它。
            pid = -1 等待任一子进程,此时 waitpid 和 wait 作用一样。
            pid < -1 等待指定进程组中的任何子进程,这个进程组的 ID 等于 pid 的绝对值。
        status : 进程退出时的状态信息。和 wait() 用法一样。
        options : options 提供了一些额外的选项来控制 waitpid()。
            0:同 wait(),阻塞父进程,等待子进程退出。
            WNOHANG:没有任何已经结束的子进程,则立即返回。
            WUNTRACED:如果子进程暂停了则此函数马上返回,并且不予以理会子进程的结
            束状态。(由于涉及到一些跟踪调试方面的知识,加之极少用到)
返回值:
     waitpid() 的返回值比 wait() 稍微复杂一些,一共有 3 种情况:
     1) 当正常返回的时候,waitpid() 返回收集到的已经回收子进程的进程号;
     2) 如果设置了选项 WNOHANG,而调用中 waitpid()还有子进程在运行,且没有子进程退出,返回0; 父
     进程的所有子进程都已经退出了返回-1;返回>0表示等到一个子进程退出

     3) 如果调用中出错,则返回-1,这时 errno 会被设置成相应的值以指示错误所在,如:当 pid 所对应的       子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid()就会出错返回,这时 errno 被
     置为 ECHILD

5【进程的补充】

1、终端

用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal),进程中,控制终端是保存在PCB中的信息,而fork会复制PCB中的信息,因此由Shell进程启动的其它进程的控制终端也是这个终端

#include<unistd.h>
char *ttyname(int fd);

功能:
    由文件描述符查出对应的文件名
参数:
    fd:文件描述符
返回值:
    成功:终端名
    失败:NULL

2、进程组

多个进程的集合
当父进程,创建子进程的时候,默认子进程与父进程属于同一进程组。

进程组ID为第一个进程ID(组长进程):
进程ID和进程组ID相同的进程就是 组长进程。
可以使用kill -SIGKILL -进程组ID(负的)来将整个进程组内的进程全部杀死只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关。 进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组)。

#include<unistd.h>
pid_t getpgrp(void); /*POSIX.1version*/
pid_t getpgid(pid_tpid);

功能:
    获取当前进程的进程组ID
    获取指定进程的进程组ID
参数:
    无
    pid:进程号,如果pid = 0,那么该函数作用和getpgrp一样
返回值:
    总是返回调用者的进程组ID

int setpgid(pid_t pid,pid_t pgid)

功能:
    改变进程默认所属的进程组。通常可用来加入一个现有的进程组或创建一个新进程组。
参数:
    将参1对应的进程,加入参2对应的进程组中
返回值:
    成功:0失败:-1

3、会话

会话是一个或多个进程组的集合。 一个会话可以有一个控制终端。
如果进程ID==进程组ID==会话ID 那么该进程为会话首进程

创建会话的步骤:
1) 调用进程不能是进程组组长,该进程变成新会话首进程(session header)
2) 该调用进程是组长进程,则出错返回 。
3) 该进程成为一个新进程组的组长进程
4) 需有root权限(ubuntu不需要)
5) 新会话丢弃原有的控制终端,该会话没有控制终端
6) 建立新会话时,先调用fork, 父进程终止,子进程调用setsid

#include<unistd.h>
pid_t getsid(pid_t pid);

功能:
    获取进程所属的会话ID
参数:
    pid:进程号,pid为0表示查看当前进程session ID
返回值:
    成功:返回调用进程的会话ID
    失败:-1

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

功能:
    创建一个会话,并以自己的ID设置进程组ID,同时也是新会话的ID。调用了setsid函数的进程,既是
    新的会长,也是新的组长。
参数:无
返回值:
    成功:返回调用进程的会话ID
    失败:-1

相关文章

网友评论

      本文标题:Linux多进程

      本文链接:https://www.haomeiwen.com/subject/lkjodjtx.html