1、信号与管道是什么?
首先了解信号与管道的意义,我们需要了解Linux系统中进程之间是如何通信的。Linux操作系统下,以进程为单位来分配或者管理资源,进程之间不能直接访问资源,因此,要求进程间的资源和信息共享就意味着进程之间能够相互通信。这就是通信机制:信号、管道。
2、进程通信的目的?
数据传输、共享数据、通知事件、资源共享、进程控制。
3、何为通信机制?
了解该机制需要明白进程是如何来互相通信的,Linux支持多种进程间的通信,IPC机制,包括共享内存、消息队列、信号量、网络通信。
好了,介绍完这些需要了解的知识后进入正题!
一、信号
信号是一种异步的通知机制,用于在软件层面模拟中断机制。当一个进程收到信号时,其行为类似于处理器接收到一个中断请求,信号属于一种软中断方式。
操作:
1.查看信号:kill -l
不可靠信号:1-31
可靠信号:34-64
杀死进程:Ctrl + C [ (2)、SIGINT ]
Ctrl + \ [ (3)、SIGQUIT ]
KILL [ (9)、SIGKILL ] kill-sig pid sig信号
内核:当我们的程序出现一些错误的时候,例如段错误等,内核会给我们的进程发送杀死当前进程的信号。
程序:通过函数发送信号:kill
2、给进程发送信号:kill
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
pid -- 你要给哪一个进程发送信号sig -- 信号(可以写编号,也可以写后面的宏定义)
成功返回 0,失败返回-1
9 -- SIGKILL -- 杀死进程,不可以被忽略或者改造;14 -- SIGALRM -- 闹钟信号,杀死进程17 -- SIGCHLD -- 只要子进程状态发生改变,父进程就能接收到该信号18 -- SIGCONT -- 恢复 被 19 号 信号 暂停 的进程19 -- SIGSTOP -- 暂停进程
3、给自己发送信号:raise
#include <signal.h>
int raise(int sig);
sig -- 信号
kill(getpid(),sig);
4、计时杀死进程:alarm
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
seconds 秒数
设置闹钟,闹钟事件到,产生闹钟信号,闹钟信号默认杀死当前进程;
如果上一次设置的有闹钟,返回上一个闹钟的剩余时间,否则返回 0;
5、产生信号再接触阻塞状态:pause
#include <unistd.h>
int pause(void);
只要运行,就阻塞,直到有一个信号产生,才会解除阻塞
6、信号处理函数:signal
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signum -- 要处理的信号handler -- SIG_DFL -- 默认处理-- SIG_IGN -- 忽略处理
signal(2,SIG_DFL); 默认处理signal(2,SIG_IGN); 忽略处理signel(信号,Fun);捕获到信号,执行 Fun 函数
7、注册退出清理函数:atexit
#include <stdlib.h>
int atexit(void (*function)(void));
//形参:函数指针
void Clean(void)
{
printf(“%s 被运行\n”,__FUNCTION__);
}
int main()
{
atexit(Clean);//注册退出清理函数,在 main 函数退出的时候,直到自动运行 Clean 函数
}
二、管道
管道(Pipe)是一种常见的进程间通信(IPC)机制,它允许两个进程通过一个半双工的通道进行数据传输。它作为两个进程之间的数据传输媒介。管道的一端连接一个写进程,另一端连接一个读进程
创建和使用:
- 创建匿名管道通常使用
pipe()
系统调用。- 使用
fork()
创建子进程后,父进程写入管道,子进程从管道中读取数据。- 写入管道通常使用
write()
系统调用,而读取管道通常使用read()
系统调用。
管道的特点:
1、无名管道
创建:pipe
#include <unistd.h>
int pipe(int pipefd[2]);
pipefd -- 整型数组,2 个元素pipefd[0]:存放的管道的读端的文件描述符pipefd[1]:存放的管道的写端的文件描述符
成功返回 0,失败返回-1;
int fd[2] = {0};pipe(fd); fd[0] fd[1]创建子进程,也得有管道,问题:先创建子进程还是先创建管道?先创建管道,子进程复制父进程资源(包含管道),
2、有名管道
1. 创建管道文件 .fifo2. 打开管道文件 open3. 读写 write read4. 关闭 close
3、创建管道文件:mkfifo
#include <sys/stat.h>
#include<sys/types.h>
int mkfifo(const char * pathname,mode_t mode)
pathname:要创建的 FIFO 文件的名字(路径+名字 以.fifo 结尾)mode: 创建的 FIFO 文件的权限
成功返回 0,失败(如果管道文件原本存在,直接返回失败)返回-1。
4、打开管道文件:open
int fd = open(char *pathname,int flag);
open 函数在打开管道文件的时候,必须两方都执行 open,open 才能打开,只有一个进程执行 open,open 会发生阻塞,直到另外的一个进程也运行到 open 的位置,两方同时解除阻塞
5、有名管道的删除:
int unlink(const char * pathname)
#include <unistd.h>
pathname:要删除的 FIFO 文件的名字(带路径)
成功返回 0,失败返回-1。