进程相关命令与函数

一、常用进程相关命令

  • ps命令
    ps -elf
    ps aux

  • top命令
    动态查看进程的情况

  • pstree命令
    打印进程树

  • kill命令
    给某个进程发送信号
    kill -9 进程号-----给进程发送SIGKILL(9号信号)
    查看所有信号
    kill -l

  • mkfifo 命令
    创建有名管道:mkfifo 管道文件路径

  • 标准IPC结构命令
    ipcs — 查询当前系统的IPC结构
    ipcrm — 删除当前系统的IPC结构(通过ID)
    命令选项:
    -a:所有的IPC
    -m:共享内存
    -q:消息队列
    -s:信号量集

二、进程API相关函数

1)获取本进程/父进程id(getpid/getppid)

头文件:
#include <sys/types.h>
#include <unistd.h>
原型:
pid_t getpid(void);
pid_t getppid(void);
返回值:
返回当前的进程ID

2)创建进程(fork/vfork函数)

  • fork函数会复制父进程的进程空间来创建一个子进程
    fork函数创建子进程之后,父子进程同时运行,从fork函数的下一行开始运行,运行的先后顺序不确定
    头文件:
    #include <unistd.h>
    原型:
    pid_t fork(void);
    返回值:
    fork函数调用1次,返回2次,父进程返回一次,子进程也返回一次,父进程返回子进程的ID,子进程返回0
    (fork函数在复制父进程时,会复制文件描述符但是不复制文件表)
    (fork函数在复制父进程时,也会复制输入输出缓冲区)

  • vfork函数也能用于创建子进程,也是通过复制父进程来产生一个子进程,vfork函数创建的子进程不会分配新的资源,抢占父进程的资源来运行,导致父进程停止运行(当子进程运行结束后,父进程重新获得资源继续运行)
    头文件:
    #include <sys/types.h>
    #include <unistd.h>
    原型:
    pid_t vfork(void);
    返回值:
    函数调用一次,返回两次,父进程返回子进程ID,子进程返回0
    (注:vfork产生的子进程必须用exit系列函数结束)

3)结束进程(exit函数和_exit/_Exit函数)

①exit函数
(是一个库函数,作用是让当前进程结束)
头文件:
#include <stdlib.h>
原型:
void exit(int status);
返回值:
让进程结束,同时给父进程提供一个8位的退出码

②_exit/_Exit函数
(_exit函数是一个系统调用,作用也是让当前进程结束,_Exit是一个宏,等价于_exit)

  • _exit
    头文件:
    #include <unistd.h>
    原型:
    void _exit(int status);
    返回值:
    让进程结束,同时给父进程提供一个8位的退出码

  • _Exit
    头文件:
    #include <stdlib.h>
    原型:
    void _Exit(int status);
    返回值:
    让进程结束,同时给父进程提供一个8位的退出码

③exit和_exit/_Exit的区别
exit函数在进程结束前,会做一些清理工作(刷新缓冲区,调用退出处理函数)
_exit/_Exit直接退出,不做以上工作

4)退出处理函数(atexit函数)

头文件:
#include <stdlib.h>
原型:
int atexit(void (function)(void));
参数:
function ---- 无参无返回值的退出处理函数
(注:当一个进程登记了多个退出处理函数时,先登记的后调用,原因是退出处理函数保存在退出处理函数栈中)

5)回收子进程的资源(wait/waitpid函数)

①wait函数
(wait系列函数可以用于回收子进程的资源并且获取其退出状态)
头文件:
#include <sys/types.h>
#include <sys/wait.h>
原型:
pid_t wait(int *status)

参数:
Status ----- 传出参数,子程序的退出状态和退出码

返回值:
成功返回退出子进程的PID,失败返回-1
(wait函数的作用是让父进程等待一个子进程结束(包括僵尸子进程),回收子进程的资源,获取其退出状态和退出码。)
(如果没有子进程结束,该函数就会导致父进程阻塞,直到有子进程结束为止)

②waitpid函数
(waitpid函数也是用于等待子进程结束,回收其资源,获取退出状态和退出码)
(waitpid可以等待指定的子进程,还可以指定等待方式)

头文件:
#include <sys/types.h>
#include <sys/wait.h>
原型:
pid_t waitpid(pid_t pid,int *status, int options);

参数:
pid ------ 等待哪些子进程
-1 ------ 等待所有子进程
大于0 ------ 等待
0 ------ 等待进程组和父进程相同的子进程
小于-1 ------ 等待进程组id为pid的绝对值的子进程
status ---- 传出参数,子程序的退出状态和退出码
options ---- 等待方式
0 — 阻塞等待
WNOHANG — 不管有没有子进程结束,都立即范围(非阻塞)

返回值:
成功返回结束子进程的pid,失败返回-1,如果非阻塞调用而且没有回收到结束的子进程,返回0
(使用waitpid函数来回收所有的僵尸子进程:while(waitpid(-1,NULL,WNOHANG));)

6)替换进程内容(exec系列函数)

exec系列函数可以用于替换进程内容,让一个进程去执行指定的全新的程序,并不会产生新的进程。
如果新的程序正常启动,旧的程序就不再继续运行。如果替换失败,旧的程序继续运行

头文件:
#include <unistd.h>
原型:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ... , char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
int execve(const char *filename, char *const argv[],char *const envp[]);

以上函数替换失败都会返回-1
l — list,可执行程序和命令行参数以列表的形式传递(一个命令行参数单独占一个函数参数的位置,以NULL结束)
v — vector,可执行程序和命令行参数以数组形式传递(用字符串数组存储所有的命令行参数,以NULL结束)
p — path,传递可执行程序只需要传递文件名,会在环境变量PATH记录的路径下寻找该文件来替换执行
e — environment,新程序替换旧程序时,可以重新传递一份环境变量表
(注:以上7个函数中,只有execve是系统调用,其他函数都是通过调用该函数来实现的)
fork()/vfork() + exec系列函数的联用,exec系列函数通常是在我们复制父进程产生子进程后,去替换子进程的内容,让子进程去执行全新的程序

三、进程之间通信

1)管道

  • 创建无名管道(PIPE)
    无名管道是管道的一种,管道文件在文件系统中不可见,只能用于有亲缘关系的进程之间的通。
    头文件:
    #include <unistd.h>
    原型:
    int pipe(int pipefd[2]);

参数:
Pipefd -----两个元素的描述符,返回无名管道的读端和写端
pipefd[0] ------ 读端
pipefd[1] ------ 写端

返回值:
成功返回0,失败返回-1
(注:管道的写端断开,读端返回0,解除阻塞;管道的读端断开,会给写端发送SIGPIPE信号,导致写端退出)

  • 创建有名管道(FIFO)
    有名管道的管道文件在文件系统可见,有名管道可以用于任意进程之间的通信。
    (对有名管道文件的操作和普通文件一样,也是 打开 — 读写 — 关闭)
    头文件:
    #include <sys/types.h>
    #include <sys/stat.h>
    原型:
    int mkfifo(const char *pathname,mode_t mode);

参数:
pathname — 管道文件路径
mode — 管道文件权限

返回值:
成功返回0,失败返回-1

2)信号

(1)修改信号的处理方式(signal函数)
头文件:
#include <signal.h>
原型:
typedef void(*sighandler_t)(int);
sighandler_t signal(int signum,sighanler_t handler);

参数:
signum:要修改哪个信号的处理方式
handler:函数指针,代表信号处理方式
SIGDFL:默认处理
SIGIGN:忽略信号
自定义函数:捕获信号

返回值:
返回值成功返回之前信号处理方式,出错返回SIG_ERR

(2)调用函数发送信号

  1. 给某个进程发信号(kill函数)
    头文件:
    #include <sys/types.h>
    #include <signal.h>
    原型:
    int kill(pid_pid ,int sig);
    返回值:
    成功返回0,失败返回-1

参数:
pid:给哪个进程发信号
0 — 给进程ID为pid的进程发信号
=0 — 给同进程组的所有进程发信号
=-1 — 给所有有发送信号权限的进程(本用户)发信号(不包括init进程)
<-1 — 给进程组ID为pid绝对值的进程组的所有进程发信号
sig:发什么信号

  1. 发信号给本进程(raise函数)
    头文件:
    #include <signal.h>
    原型:
    in raise(int sig);

参数:
sig :发送的信号

  1. 产生闹钟信号(alarm函数)
    (该函数会在延时指定的秒数后给本进程发送SIGALRM信号,该信号默认让进程退出)
    头文件:
    #include <unistd.h>
    原型:
    unsigned int alarm(unsigned int seconds);

参数:
seconds — 闹钟的秒数

  1. 阻塞进程,等待信号(pause函数)
    (该函数让进程睡眠,直到收到让进程终止或者被捕获的信号)
    头文件:
    #include <unistd.h>
    原型:
    int pause(void);

  2. 发送信号函数(带有额外数据)(sigqueue函数)
    头文件:
    #include <signal.h>
    原型:
    int sigqueue(pid_t pid,int sig,const union sigval value);
    union sigval {
    int sival_int;
    void *sival_ptr;
    };

参数:
前两个参数和kill相同
value:发送信号时额外带的数据
返回值也和kill一样

  1. 信号屏蔽的实现(sigprocmask函数)
    头文件:
    #include<signal.h>
    原型:
    int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
    返回值:
    成功返回0,失败返回-1

参数:
how:信号屏蔽方式
SIG_BLOCK — 相当于旧的屏蔽+新的屏蔽
(A B C + C D E —> A B C D E)
SIG_UNBLOCK — 相当于旧的屏蔽-新的屏蔽
(A B C - C D E —> A B)
SIG_SETMASK — 直接使用新的屏蔽
(A B C / C D E —> C D E)
set:新的屏蔽的信号集
oldset:传出参数,传出旧的屏蔽的信号集

  1. 信号屏蔽期间查看收到哪些信号(sigpending函数)
    头文件:
    #include<signal.h>
    原型:
    int sigoending(sigset_t *set);

参数:
set ----传出参数,屏蔽期间收到的信号

  1. 信号集
    头文件:
    #include <signal.h>
    原型:
    int sigemptyset(sigset_t *set);//将信号集置空
    int sigfillset(sigset_t *set);//将信号集填满
    int sigaddset(sigset_t *set, int signum);//添加信号到信号集
    int sigdelset(sigset_t *set, int signum);//从信号集删除信号
    int sigismember(const sigset_t *set, int signum);//查找信号集中有没有某个信号
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值