进程间通信

一、无名管道

1.1 Linux下进程间通信概述

1.2 无名管道通信

无名管道是内核空间实现的机制,只能用于亲缘进程间通信,无名管道的大小是64KB;

1.3 pipe函数

项目 内容
所需头文件 #include <unistd.h>
函数原型 int pipe(int pipefd[2]);
功能 创建单向数据通道(半双工通信方式)。数据只能从读端 pipefd[0] 读取,从写端 pipefd[1] 写入,方向不可逆转;数据先写入内核缓冲区,再由读进程从内核缓冲区读取。
参数 pipefd:用于存放管道读写两端的文件描述符的数组首地址
返回值(成功) 0
返回值(失败) -1,并重置错误码

1.4 无名管道

类别 特点描述
通信范围 依托具有亲缘关系的进程间的文件描述符继承特性来实现通信(如父子进程、兄弟进程)
数据传输方向 数据只能单向传输,符合半双工定义(一端读、一端写)
内核缓冲区大小 多数 Linux 系统中默认大小为 64KB
lseek 限制 不能使用 lseek 函数(管道不是普通文件),调用会返回 -1
读端存在时(写满) 写管道满则阻塞;存在约 4KB 空间时唤醒(Linux 内核为平衡效率与响应性的设计)
读端不存在时(写) 写管道会破裂,触发 SIGPIPE 信号
写端存在时(读) 读管道时若无数据,则阻塞等待
写端不存在时(读) 读管道时若无数据,则立即返回 0(非阻塞,类似读到文件结束)

二、有名管道

2.1 有名管道通信

有名管道可以用于亲缘进程通信,也可以用于非亲缘进程通信,有名管道的大小是64KB;

2.2 mkfifo函数

项目 内容
所需头文件 #include <sys/types.h> #include <sys/stat.h>
函数原型 int mkfifo(const char *pathname, mode_t mode);
功能 创建有名管道(FIFO)
参数 **pathname:**文件的路径和名字(只写名字则默认路径是当前路径)。如果管道文件已存在,则会报错(提示文件已存在) mode: 文件的权限。最终权限 = mode & ~umask
返回值(成功) 0
返回值(失败) -1,并重置错误码

2.3 unlink函数

项目 内容
所需头文件 #include <unistd.h>
函数原型 int unlink(const char *pathname);
功能 删除文件系统中的"文件名链接"(减少文件的硬链接计数,当计数归零且无进程打开时,删除文件内容)
参数 **pathname:**文件的路径和名字(只写名字则默认路径是当前路径)
返回值(成功) 0
返回值(失败) -1,并重置错误码

2.4 有名管道

类别 特点描述
数据传输方向 数据只能单向传输,符合半双工定义;若要双向通信,需创建两个管道
内核缓冲区大小 多数 Linux 系统中默认大小为 64KB
lseek 限制 不能使用 lseek 函数(管道不是普通文件),调用会返回 -1
写操作 - 读端已打开时 写入数据时会尽可能写入(受管道缓冲区大小限制);若管道已满,写操作会阻塞直到有空间
写操作 - 阻塞期间读端关闭 会产生 SIGPIPE 信号(管道破裂)
写操作 - 读端未打开(阻塞方式) 写进程在 open() 调用时会阻塞,直到有读进程打开该 FIFO
写操作 - 读端未打开(非阻塞方式) open() 调用会直接返回错误
读操作 - 写端已打开时 读取数据时,有多少读取多少;若管道为空,读操作会阻塞等待数据写入
读操作 - 写端未打开时 读进程在 open() 调用时会阻塞,直到有写进程打开该管道
读操作 - 写端曾打开但已关闭 读操作会读取剩下数据,读完后返回 0(不会阻塞,类似读到文件结束)
读操作 - 非阻塞方式打开且无写端 open() 调用会直接返回成功

三、信号

先导

信号是中断的一种软件模拟,它是基于linux内核实现的;

用户可以给进程发信号,进程可以给进程发信号,linux内核也可以给进程发信号;

对信号处理的三种方式:默认、忽略、捕捉;

3.1 常用信号

信号名 含义 默认操作
SIGKILL 用来结束进程,且不能被捕捉和忽略 终止
SIGSTOP 用于暂停进程,且不能被捕捉和忽略 暂停进程
SIGTSTP 用于暂停进程,用户可键入 SUSP 字符(通常是 Ctrl+Z)发出此信号 暂停进程
SIGCONT 让进程进入运行态 继续运行
SIGALRM 通知进程定时器时间已到 终止
SIGUSR1 / SIGUSR2 保留给用户程序使用 终止
SIGCHLD 当子进程退出时,给父进程发送该信号 忽略

3.2 signal函数

项目 内容
所需头文件 #include <signal.h>
函数原型 typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
功能 建立信号与处理方式的关联
参数 - signum 信号的编号
参数 - handler 处理方式: • SIG_IGN:忽略 • SIG_DFL:默认 • 传递函数地址:捕捉
返回值(成功) 返回 handler 首地址
返回值(失败) 返回 SIG_ERR,并重置错误码

3.3 raise函数

项目 内容
所需头文件 #include <signal.h>
函数原型 int raise(int sig);
功能 向自身发送指定的信号
参数 - sig 要发送的信号的编号
返回值(成功) 返回 0
返回值(失败) 返回 非0

3.4 kill函数

项目 内容
所需头文件 #include <sys/types.h> #include <signal.h>
函数原型 int kill(pid_t pid, int sig);
功能 给任意进程发送信号
参数 - pid 发送信号的目标: • >0:向 pid 对应的单个进程 发送信号(最常用场景) • 0:向同进程组 的所有进程发送信号 • -1:向所有有权限操作的进程 发送信号(init进程除外,避免影响系统核心进程) • < -1:给进程组ID等于 -pid 的进程发送信号
参数 - sig 信号的编号
返回值(成功) 0
返回值(失败) -1,并重置错误码

3.5 atoi函数

项目 内容
所需头文件 #include <stdlib.h>
函数原型 int atoi(const char *nptr);
功能 将字符串转换为整数
参数 - nptr 要转换的字符串的首地址
返回值(成功) 返回转换后的整数
返回值(失败) 返回 0;如果转换后整数超出 int 范围,则行为未定义
相关推荐
张小姐的猫2 小时前
【Linux】进程信号(上)—— 信号产生 | 保存信号
linux·运维·服务器
石小千2 小时前
部署Nextcloud与Onlyoffice(二)安装Onlyofiice
linux·运维
xuanwenchao2 小时前
Mac M1/M2/M3/M4/M5芯片-系统安装Ubuntu
linux·ubuntu·macos
白毛大侠2 小时前
Docker vs 虚拟机 vs Go 用户态/内核态:这三组概念
运维·docker·golang·kvm
小白勇闯网安圈2 小时前
腾讯云服务器部署Dify
服务器·人工智能·云计算·腾讯云
芝士就是力量啊 ೄ೨2 小时前
提高服务器安全-采用密钥公钥登录而非密码登录-详细操作步骤
运维·服务器·安全
渠过客3 小时前
【运维】PM2 使用完全指南:Node.js 应用进程管理利器
运维·node.js
不会写DN3 小时前
处理 TCP 流中的消息分片
服务器·网络·tcp/ip
木下~learning3 小时前
Linux 驱动:RK3399 从零手写 GT911 电容触摸屏驱动(完整可运行)
linux·运维·服务器