公共数据开放网站建设,外贸网站建设网站,移动端开发工程师,教育培训机构推荐0x00.概述
本文将基于linux系统介绍进程间通信的几种方式#xff0c;包括匿名管道#xff0c;命名管道#xff0c;systemV的共享内存等#xff0c;全是干货#xff0c;无废话
0x01.匿名管道
匿名管道#xff1a; 通过调用 pipe 函数创建的#xff0c;它在内存中创建一…
0x00.概述
本文将基于linux系统介绍进程间通信的几种方式包括匿名管道命名管道systemV的共享内存等全是干货无废话
0x01.匿名管道
匿名管道 通过调用 pipe 函数创建的它在内存中创建一个缓冲区用于父子进程之间的通信。这个缓冲区通常是在内核的地址空间中分配的而不是在文件系统中创建文件。因此数据通过这个内存缓冲区进行传递而不涉及真实的文件。匿名管道主要用于相关的父子进程之间的通信。
1.代码实现
#include unistd.h
#include stdio.hint main() {int pipefd[2];pipe(pipefd);pid_t child_pid fork();if (child_pid -1) {perror(fork);return 1;}if (child_pid 0) {// Parent Processclose(pipefd[0]); // 关闭读取端// 向管道写入数据const char *message Hello, Pipe!;write(pipefd[1], message, 13);close(pipefd[1]); // 关闭写入端} else {// Child Processclose(pipefd[1]); // 关闭写入端// 从管道读取数据char buffer[50];read(pipefd[0], buffer, sizeof(buffer));printf(Child Process: Received message: %s\n, buffer);close(pipefd[0]); // 关闭读取端}return 0;
}
2.代码讲解
创建时pipe接收一个输出型参数创建成功返回fd[0]和fd[1],分别对应管道的读和写端子进程写父进程读很好理解。
0x02.命名管道
命名管道 通过调用 mkfifo 函数创建的它在文件系统中创建一个特殊类型的文件。当进程使用命名管道进行通信时数据通过文件系统的路径来传递。尽管文件系统中有一个相关的文件但实际上数据仍然是通过内存缓冲区传递的。但与匿名管道不同命名管道提供了一个在文件系统中可见的标识符允许独立的进程通过文件路径来访问这个管道
1.代码实现
#include fcntl.h
#include stdio.h
#include stdlib.h
#include string.h
#include sys/types.h
#include sys/stat.h
#include unistd.hint main() {const char *fifoPath /tmp/myfifo;// 创建命名管道mkfifo(fifoPath, 0666);// 创建子进程pid_t child_pid fork();if (child_pid -1) {perror(fork);return 1;}if (child_pid 0) {// 子进程写入数据到命名管道int fd open(fifoPath, O_WRONLY);const char *message Hello, FIFO!;write(fd, message, strlen(message));close(fd);} else {// 父进程读取数据从命名管道int fd open(fifoPath, O_RDONLY);char buffer[100];read(fd, buffer, sizeof(buffer));printf(Parent Process: Received message: %s\n, buffer);close(fd);// 等待子进程结束wait(NULL);// 删除命名管道unlink(fifoPath);}return 0;
}2代码讲解
int mkfifo(const char *pathname, mode_t mode)
总结命名管道就是在磁盘上中创建了一个特殊的文件这个文件可以被打开但是打开后不会将内存中的数据刷新到磁盘。在磁盘上就有了路径而路径是唯一的所以双方就可以通过文件的路径来看到同一份资源即管道文件。
0x03管道总结
1.管道是用来进行具有血缘关系的进程进行进程间通信 常用于父子间通信
2.管道具有通过让进程间协同提供了访问控制父子进程会相互协调进行读写操作
3.管道提供的是面向字节流式的通信服务 --- 面向字节流 --- 通过定制协议实现父进程多次写入子进程一次性读取
4.管道是基于文件的文件的生命周期是随进程的即管道的生命周期也随进程的数据通过内存缓冲区传递
5.管道是单向通信的就是半双工通信的一种特殊方式.一边写完另一边才能读类似对讲坤
0x04.SystemV
1.原理图 2.理解
1.当共享内存创建出来后通过系统调用挂接到对应的进程当中操作系统会给进程分配一个mm_struct上的虚拟地址空间在堆栈之间的共享代码区通过页表建立与物理内存的映射从而实现对共享内存的访问
2.共享内存块不属于某个进程而属于操作系统。
3不同于pipe和fifo通过readwrite来进行通信共享内存属于用户空间可以直接进行内存级的读和写。 3.实现
实现共享内存间通信分为以下几步创建共享内存将进程挂接到共享内存使用共享内存分离进程与共享内存删除共享内存
先引入头文件 创建(create) shmget 第一个参数指定相同的key调用一个类似哈希的算法ftok求出一个相同的值
第二个参数指定共享内存的大小一般是4096字节页的整数倍
第三个参数:设置选项后还可以加权限一般是0666
1.IPC_CREATE创建共享内存如果底层已经存在则获取并返回如果不存在则创建共享内存然后再返回 2.IPC_EXCL单独使用它没有意义一般和IPC_CREATE合起来使用见下 3.IPC_CREATE | IPC_EXCL如果底层不存在则创建共享内存并返回如果底层存在则出错返回。言外之意如果返回成功那么一定是一个全新的内存块
ftok()
一般用项目所在路径名和工程编号生成一个随机值
挂接attach shmat()
函数接受三个参数
shmid共享内存段的标识符ID即通过调用 shmget() 函数创建共享内存时返回的 shmid。表示你想挂接哪一个共享内存。
shmaddr共享内存段连接到进程地址空间的首地址。通常将其设置为 NULL指示系统选择适当的地址。如果想要指定特定的地址可以传递一个非空的地址值。但不建议这样使用。
shmflg标志参数用于指定连接共享内存的选项。常用的选项有
SHM_RDONLY以只读方式连接共享内存不允许写入。 SHM_RND将 shmaddr 参数忽略系统选择一个地址以进行连接。
char* shmaddr (char*)shmat(shmid,nullptr,SHM_RDONLY);
一般需要强转为我们需要的类型
使用use
略
分离detach
shmdt 成功返回0失败返回-1
删除remove
手动删除
在终端输入ipcs -m 查看共享内存使用情况
输入ipcrm -m shmid 删除共享内存
代码删除shmctl shmid共享内存段的标识符ID即通过调用 shmget() 函数创建共享内存时返回的 shmid。
cmd控制命令用于指定要执行的操作类型。可以使用以下命令之一
IPC_STAT获取共享内存段的状态信息将结果存储在 buf 参数指向的 struct shmid_ds 结构体中。 IPC_SET设置共享内存段的状态信息使用 buf 参数中提供的值。 IPC_RMID删除共享内存段将其标记为删除状态并在释放最后一个进程的附加段之后销毁。 buf一个指向 struct shmid_ds 结构体的指针用于传递或接收共享内存段的状态信息。 int n shmctl(shmid,IPC_RMID,nullptr);以上就是全部内容能力有限如果觉得对你有帮助请点赞支持一下吧