1. Unix IPC(InterProcess Communication)

同一主机的各个进程间的IPC:管道、FIFO、消息队列、信号量、共享存储器

不同主机上的各个进程间IPC:socket套接字

2. 管道

管道进行IPC有两个局限:
(1) 半双工,即数据只能在一个方向上流动
(2) 只能在具有公共祖先的进程之间使用。通常,一个管道由一个进程创建,然后该进程调用fork,此后 父子进程之间可以使用该管道
fstat函数对管道的每一端都返回一个FIFO类型的文件描述符,可以用S_ISFIFO宏来测试管道
通常是一个进程调用pipe函数创建管道,紧接着调用fork,这样就创建了从父进程到子进程的IPC通道
 
对于从父进程到子进程的管道,父进程关闭 管道的读端(fd[0])子进程关闭管道的写端(fd[1])
 
popen、pclose两个函数实现的操作是:创建一个管道,调用fork产生一个子进程,关闭管道的不使用端,执行一个shell以运行命令,最后等待命令终止
#include <stdio.h>FILE* popen(const char* cmdstring, const char* type);
int   pclose(FILE* fp);

函数popen先执行fork,然后调用exec以执行cmdstring,并且返回一个标准I/O文件指针

type为“r”表示可读,为“w”表示可写
简单实现一个popen:
 1 #include <unistd.h>
 2 #include <stdio.h>
 3 #include <errno.h>
 4 #include <sys/wait.h>
 5 #include <fcntl.h>
 6
 7 /* pointer to array allocated at run-time */
 8 static pid_t* childpid = NULL;
 9
10 /* from our open_max() */
11 static int maxfd;
12
13 FILE* my_popen(const char* cmdstring, const char* type)
14 {
15     int pfd[2];
16     pid_t pid;
17
18     /* only allow type = "r" or "w" */
19     if ((type[0] != 'r' && type[0] != 'w') || type[1] != 0) {
20         errno = EINVAL;
21         return NULL;
22     }
23        childpid = (pid_t*)calloc(maxfd, sizeof(pid_t));
24         if (childpid == NULL) {
25             return NULL;
26         }
27     }
28
29     if (pipe(pfd) < 0) {
30         return NULL;
31     }
32
33     if ((pid = fork()) < 0) {
34         return NULL;
35     } else if (pid == 0) {      /* child */
36         if (*type == 'r') {
37             close(pfd[0]);
38             if (pfd[1] != STDOUT_FILENO) {
39                dup2(pfd[1], STDOUT_FILENO);
40                 close(pfd[1]);
41             }
42         } else {
43             close(pfd[1]);
44             if (pfd[0] != STDIN_FILENO) {
45                 dup2(pfd[0], STDIN_FILENO);
46                 close(pfd[0]);
47             }
48         }
49
50         /* close all fds in childpid[] */
51         for (int i = 0; i < maxfd; ++i) {
52             if (childpid[i] > 0) {
53                 close(i);
54             }
55         }
56
57     }
58
59     /* parent continue */
60     FILE* fp;
61     if (*type == 'r') {
62         close(pfd[1]);
63         if ((fp = fdopen(pfd[0], type)) == NULL) {
64             return NULL;
65         }
66     } else {
67         close(pfd[0]);
68         if ((fp = fdopen(pfd[1], type)) == NULL) {
69            return NULL;
70         close(pfd[0]);
71         if ((fp = fdopen(pfd[1], type)) == NULL) {
72             return NULL;
73         }
74     }
75
76     childpid[fileno(fp)] = pid;
77     return fp;
78 }

3. 消息队列

消息队列是消息的链接表,存放在内核中并由消息队列ID标识
msgget用于创建一个新队列或打开一个现存的队列
msgsnd将新消息添加到队列尾端
msgrcv用户从队列中取消息

4. 信号量

信号量是一个计数器,用于多进程对共享数据对象的访问

5. 共享存储器

共享存储器允许多个进程共享一个给定的存储区,因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的IPC
使用共享存储区时必须确保 多个进程之间对给定的存储区的同步访问,通常,信号量被用来实现对共享存储区的同步访问
#include <sys/shm.h>
/* 获得共享存储标识符 */
int shmget(key_t key, size_t size, int flag);/* 对共享存储区执行多种操作 */
int shmctl(int shmid, int cmd, struct shmid_ds* buf);/* 进程将共享存储区连接到它的地址空间中 */
void* shmat(int shmid, const void* addr, int flag);

如果addr为0,则此段连接到内核选择的第一个可用地址上。一般将addr指定为0,以便由内核选择地址

打印各种不同类型的数据所存放的位置:

 1 #include <unistd.h>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <sys/shm.h>
 5
 6 #define ARRAY_SIZE 40000
 7 #define MALLOC_SIZE 100000
 8 #define SHM_SIZE 100000
 9 #define SHM_MODE 0600  /* user read/write */
10
11 char array[ARRAY_SIZE];   /* uninitialized data = bss */
12
13 int main(int argc, char* argv[])
14 {
15     int shmid;
16     char* ptr = NULL;
17     char* shmptr = NULL;
18
19     fprintf(stdout, "array[] from %p to %p\n", array, array + ARRAY_SIZE);
20     fprintf(stdout, "stack around %p\n", &shmid);
21     ptr = (char*)malloc(MALLOC_SIZE);
22     if (ptr == NULL) {
23         fprintf(stderr, "malloc error\n");
24     }
25
26     fprintf(stdout, "malloc from %p to %p\n", ptr, ptr + MALLOC_SIZE);
27
28     shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE);
29     if (shmid < 0) {
30         fprintf(stderr, "shmget error\n");
31     }
32
33     shmptr = shmat(shmid, 0, 0);
34     if (shmptr == (void*)-1) {
35         fprintf(stderr, "shmat error\n");
36     }
37
38     fprintf(stdout, "shared memory from %p to %p\n", shmptr, shmptr + SHM_SIZE);
39     if (shmctl(shmid, IPC_RMID, 0) < 0) {
40         fprintf(stderr, "shmctl error\n");
41     }
42     free(ptr);
43     return 0;
44 }

在基于Intel的Linux系统上运行此程序,其输出如下:

如果mmap函数指定了 MAP_SHARED标志,则此存储映射区可被多个进程共享
匿名存储映射:调用mmap时指定MAP_ANON标志,并将文件描述符指定为-1,结果得到的映射区域是匿名的,因为并不与一个文件描述符相关联

转载于:https://www.cnblogs.com/wwwjieo0/p/3739107.html

APUE 学习笔记(十) 高级I/O相关推荐

  1. 吴恩达《机器学习》学习笔记十——神经网络相关(2)

    吴恩达<机器学习>学习笔记十--神经网络相关(2) 一. 代价函数 二. 反向传播算法 三. 理解反向传播算法 四. 梯度检测 五. 随机初始化 1.全部初始化为0的问题 2.随机初始化的 ...

  2. Python语言入门这一篇就够了-学习笔记(十二万字)

    Python语言入门这一篇就够了-学习笔记(十二万字) 友情提示:先关注收藏,再查看,12万字保姆级 Python语言从入门到精通教程. 文章目录 Python语言入门这一篇就够了-学习笔记(十二万字 ...

  3. 【现代机器人学】学习笔记十二:轮式移动机器人

    目录 轮式机器人类型 全向轮式机器人 建模 单个全向轮是怎么运动的 多个全向轮是如何带动底盘运动的 运动规划和反馈控制 非完整约束轮式移动机器人 建模 独轮车 差速驱动机器人 车型机器人 非完整移动机 ...

  4. IOS之学习笔记十五(协议和委托的使用)

    1.协议和委托的使用 1).协议可以看下我的这篇博客 IOS之学习笔记十四(协议的定义和实现) https://blog.csdn.net/u011068702/article/details/809 ...

  5. 吴恩达《机器学习》学习笔记十四——应用机器学习的建议实现一个机器学习模型的改进

    吴恩达<机器学习>学习笔记十四--应用机器学习的建议实现一个机器学习模型的改进 一.任务介绍 二.代码实现 1.准备数据 2.代价函数 3.梯度计算 4.带有正则化的代价函数和梯度计算 5 ...

  6. 吴恩达《机器学习》学习笔记十二——机器学习系统

    吴恩达<机器学习>学习笔记十二--机器学习系统 一.设计机器学习系统的思想 1.快速实现+绘制学习曲线--寻找重点优化的方向 2.误差分析 3.数值估计 二.偏斜类问题(类别不均衡) 三. ...

  7. Mr.J-- jQuery学习笔记(十九)--自定义动画实现图标特效

    之前有写过自定义动画Mr.J-- jQuery学习笔记(十八)--自定义动画 这次实现一个小demo 图标特效 页面渲染 <!DOCTYPE html> <html lang=&qu ...

  8. Mr.J-- jQuery学习笔记(十六)--展开和收起动画折叠菜单的实现

    之前写过动画的隐藏与显示:Mr.J-- jQuery学习笔记(十四)--动画显示隐藏 动画隐藏与显示的一个小demo--对联广告:Mr.J-- jQuery学习笔记(十五)--实现页面的对联广告 与动 ...

  9. Mr.J-- jQuery学习笔记(十五)--实现页面的对联广告

    请看之前的:Mr.J-- jQuery学习笔记(十四)--动画显示隐藏 话不多说,直接上demo <!DOCTYPE html> <html lang="en"& ...

最新文章

  1. struts 2 结合json
  2. vue-cli的webpack模板项目配置文件分析
  3. android dialog
  4. python将图片转动漫_如何把照片变成手绘动漫化?
  5. [Python从零到壹] 三十五.图像处理基础篇之OpenCV绘制各类几何图形
  6. twisted系列教程十三–deferred 中的deferred
  7. Zuul异常Zuul spring cloud zuul com.netflix.zuul.exception.ZuulException GENERAL
  8. 为什么某些地方结婚彩礼那么高呢?而广东却很低甚至不需要?
  9. 查询记录rs.previous()使用
  10. java 同余法产生随机数_线性同余法生成为随机数
  11. SC软件结构图_例题
  12. 毕业论文排版,格式总结
  13. 2022-07微软漏洞通告
  14. 计算机等级考试sumif,sumif函数的使用方法有哪些
  15. Floyd最短路径算法
  16. NYOJ-599-奋斗的小蜗牛-2013年11月4日22:22:22
  17. Android中的Glide
  18. 2012 SDCC中国软件开发者大会门票社区团购火热开启!
  19. 2021年全球零售电子商务软件收入大约6686.2百万美元,预计2028年达到12000百万美元,2022至2028期间,年复合增长率CAGR为9.4%
  20. 记一次IBM面试经历

热门文章

  1. keil流水灯c语言程序两个一起亮,Keil单片机点亮一个灯及循环流水灯三种实现方法详解...
  2. c++设置一个二维字符组初值_6.8 C++字符数组
  3. linux 访问centos共享,CentOS访问Windows共享
  4. 一阶广义差分模型_贵州茅台(600519)股价预测 (ARIMA模型)
  5. 将自己的dcm数据制作成LUNA16数据集提供数据样式之代码整理
  6. 网络监视工具nethogs命令
  7. 数据流程图 符号说明
  8. 多项目Node版本控制
  9. Spring Cloud 架构 五大神兽的功能
  10. c/c++标准库中的文件操作总结