嵌入式开发学习日志(linux系统编程--系统编程之 进程间通信IPC)Day32

一、引言

空间独立,需要一些操作;

分为三大类:

1、古老的通信方式

无名管道 有名管道 信号

2、IPC对象通信 system v BSD suse fedora kernel.org

消息队列(用的相对少,这里不讨论)

共享内存

信号量集

3、socket通信

网络通信(不同主机间交互)

二、 管道

无名管道 ===》pipe ==》只能给有亲缘关系进程通信

有名管道 ===》fifo ==》可以给任意单机进程通信
管道特性:

1、管道是 半双工的工作模式

2、所有的管道都是特殊的文件不支持定位操作。不支持lseek->> fd fseek ->>FILE*

3、管道是特殊文件,读写使用文件IO。

其中具有缓冲区,可以考虑,如果是字符串的话,使用fgets,fread,fgetc,

最好使用:open,read,write,close;
四句真言(使用的关键)

1.读端存在,一直向管道中去写,超过64k,写会阻塞。

2.写端是存在的,读管道,如果管道为空的话,读会阻塞。(读阻塞)

3.管道破裂,,读端关闭,写管道。

set follow-fork-mode parent

使用gdb调试时,敲上面的命令,进入子进程,一般默认父进程

  1. read 0 ,写端关闭,如果管道没有内容,read 0 ;

三、管道操作步骤

使用框架:

创建管道 ==》读写管道 ==》关闭管道

1、无名管道 ===》管道的特例 ===>pipe函数

特性:
1.1 亲缘关系进程使用
1.2 有固定的读写端


流程:

创建并打开管道: pipe函数

#include <unistd.h>
int pipe(int pipefd[2]);

功能:创建并打开一个无名管道

参数:pipefd[0] ==>无名管道的固定读端

pipefd[1] ==>无名管道的固定写端

返回值:成功 0

失败 -1;

注意事项:
1、无名管道的架设应该在fork之前进行。
无名管道的读写:===》文件IO的读写方式。
读: read()
写: write()

关闭管道: close();

实现照片复制:


1、父子进程是否都有fd[0] fd[1],

如果在单一进程中写fd[1]能否直接从fd[0]中读到。

可以,写fd[1]可以从fd[0]读

2、管道的数据存储方式是什么样的

数据是否一直保留?

栈, 先进后出

队列形式存储 读数据会剪切取走数据不会保留

先进先出

3、管道的数据容量是多少,有没有上限值。

操作系统的建议值: 512* 8 = 4k

代码测试实际值: 65536byte= 64k

4、管道的同步效果如何验证?读写同步验证。

读端关闭能不能写? 不可以 ===>SIGPIPE 异常终止

写端关闭能不能读? 可以,取决于pipe有没有内容,===>read返回值为0 不阻塞

结论:读写端必须同时存在,才能进行管道的读写。

5、固定的读写端是否就不能互换?

能否写fd[0] 能否读fd[1]? 不可以,是固定读写端。


四、有名管道(本机上的不同进程)

有名管道===》fifo ==》有文件名称的管道。
文件系统中可见

4.1 使用步骤

框架:

创建有名管道 ==》打开有名管道 ==》读写管道 ==》关闭管道 ==》卸载有名管道

4.2 所需函数

1. mkfifo

#include <sys/types.h>

#include <sys/stat.h>

remove();

int mkfifo(const char *pathname, mode_t mode);

功能:在指定的pathname路径+名称下创建一个权限为

mode的有名管道文件。

参数:pathname要创建的有名管道路径+名称

mode 8进制文件权限。权限一般0666

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

2、打开有名管道 open

注意:该函数使用的时候要注意打开方式,

因为管道是半双工模式,所有打开方式直接决定

当前进程的读写方式。

一般只有如下方式:

int fd-read = open("./fifo",O_RDONLY); ==>fd 是固定读端

int fd-write = open("./fifo",O_WRONLY); ==>fd 是固定写端

不能是 O_RDWR 方式打开文件。

不能有 O_CREAT 选项,因为创建管道有指定的mkfifo函数

3、管道的读写: 文件IO

读: read(fd-read,buff,sizeof(buff));

写: write(fd-write,buff,sizeof(buff));

4、关闭管道:

close(fd);

5、卸载管道:remove();

int unlink(const char *pathname);

功能:将指定的pathname管道文件卸载,同时

从文件系统中删除。

参数: ptahtname 要卸载的有名管道

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

复制图片:

有名管道

1、是否需要同步,以及同步的位置。

读端关闭 是否可以写,不能写什么原因。

写端关闭 是否可以读。

结论:有名管道执行过程过必须有读写端同时存在。

如果有一端没有打开,则默认在open函数部分阻塞。

2、有名管道是否能在fork之后的亲缘关系进程中使用。

结论: 可以在有亲缘关系的进程间使用。

注意: 启动的次序可能会导致其中一个稍有阻塞。

3、能否手工操作有名管道实现数据的传送。

读: cat fifoname

写: echo "asdfasdf" > fifoname

五、信号通信

应用:异步通信。 中断..

1~64;32应用编程。

//关闭

Term Default action is to terminate the process.

//忽略

Ign Default action is to ignore the signal.

wait

// 关闭,并保存关键点信息

Core Default action is to terminate the process and dump core (see

core(5)).

gdb a.out -c core

//暂停

Stop Default action is to stop the process.

//继续

Cont Default action is to continue the process if it is currently stopped.

1.信号 kill -l ==>前32个有具体含义的信号

信号的含义详见图片

2.kill -xx xxxx

发送进程 信号 接收进程

kill -9 1000

a.out 9 1000 发送端:

复制代码
   #include <sys/types.h>
    #include <signal.h>
 
    int kill(pid_t pid, int sig);

功能:通过该函数可以给pid进程发送信号为sig的系统信号。

参数:pid 要接收信号的进程pid

sig 当前程序要发送的信号编号 《=== kill -l

返回值:成功 0

失败 -1;

3.raise(与kill相似)

int raise(int sig)== kill(getpid(),int sig);

功能:给进程自己发送sig信号

4.alarm

unsigned int alarm(unsigned int seconds);

SIGALAM

功能:定时由系统给当前进程发送信号,也称为闹钟函数

闹钟只有一个,定时只有一次有效,

但是必须根据代码逻辑是否执行判断。

5、pause

int pause(void);

功能:进程暂停,不再继续执行,除非 收到其他信号。

接收端

每个进程都会对信号作出默认响应,但不是唯一响应。

一般如下三种处理方式:

1、默认处理

2、忽略处理 9,19

3、自定义处理 9,19 捕获

信号注册函数原型:(回调函数)

void ( *signal(int signum, void (*handler)(int)) ) (int);

typedef void (*sighandler_t)(int);

===》void (*xx)(int); == void fun(int);

===》xx是 void fun(int) 类型函数的函数指针

===》typedef void(*xx)(int) sighandler_t; ///错误

typedef int myint;

===>sighandler_t signal(int signum, sighandler_t handler);

===> signal(int sig, sighandler_t fun);

===> signal(int sig, xxx fun);

===>fun 有三个宏表示:SIG_DFL 表示默认处理

SIG_IGN 表示忽略处理

fun 表示自定义处理

6、SIGCHLD

实际上,在子进程结束的时候,会产生一个SIGCHLD信号,信号描述如下,根据man手册可以知道,子进程结束运行,其父进程会收到SIGCHLD信号,该信号的默认处理动作是忽略。

SIGCHLD信号产生的条件主要有以下几个:

  • 子进程终止时;

  • 子进程接收到SIGSTOP信号停止时;

  • 子进程处在停止态,接受到SIGCONT后唤醒时;

7、 信号处理函数中的num,代表的是该信号的数字

相关推荐
自动驾驶小卡35 分钟前
ubuntu 常用操作指令(与域控制器交互相关)
linux·ubuntu·操作指令
靡樊41 分钟前
Socket编程UDP\TCP
网络·c++·学习·tcp/ip·udp
余渔鱼112341 分钟前
ajax学习手册
学习·ajax·okhttp
东京老树根1 小时前
SAP学习笔记 - 开发24 - 前端Fiori开发 Filtering(过滤器),Sorting and Grouping(排序和分组)
笔记·学习
意如流水任东西1 小时前
Linux开发工具(apt,vim,gcc)
linux·服务器
XMAIPC_Robot1 小时前
基于RK3568的多网多串电力能源1U机箱解决方案,支持B码,4G等
linux·fpga开发·能源·边缘计算
程序猿小D1 小时前
第14节 Node.js 全局对象
linux·前端·npm·node.js·编辑器·vim
文牧之1 小时前
Oracle 的 SEC_CASE_SENSITIVE_LOGON 参数
运维·数据库·oracle
Antonio9152 小时前
【Linux】 Linux 进程控制
linux·运维·服务器