2019独角兽企业重金招聘Python工程师标准>>>

15.6 XSI IPC

(1)3种称作XSI IPC的IPC是:

1)消息队列

2)信号量

3)共享存储器

(2)标识符和键

1)标识符:是一个非负整数,用于引用IPC结构。是IPC对象的内部名。

2)键:IPC对象的外部名。可使多个合作进程能够在同一IPC对象上汇聚。

(3)IPC_PRIVATE键:

用于创建一个新的IPC结构。不能指定此键来引用一个现有的IPC结构。

(4)ftok函数:

由一个路径名和项目ID产生一个键。

(5)ipc_perm结构体

规定了ipc结构的权限和所有者。

(6)结构限制:

XSI IPC结构都有内置限制,可通过重新配置内核来改变。

1)sysctl命令:观察、修改内核配置参数。

2)ipcs -l:显示ipc相关限制。

(7)IPC结构和管道、FIFO的区别:

IPC结构在系统范围内起作用,且没有引用计数。

(8)IPC结构在文件系统中没有名字;IPC不使用文件描述符。


15.7 消息队列

(1)新的应用程序中不要使用消息队列。它们有缺点。(15.6.4)

(2)客户进程和服务器进程之间的双向数据流,可以使用消息队列或全双工管道。


15.8 信号量

(1)多个进程间共享一个资源,可以使用信号量、记录锁和互斥量中的一种来协调。

(2)共享存储中的互斥量速度最快,但作者依然喜欢使用记录锁的两个原因:

1)<459>

2)<459>


15.9 共享存储

(1)共享存储的作用:

允许两个或多个进程共享一个给定的存储区。

它是最快的一种IPC,因为数据不需要在客户进程和服务器进程之间复制。

(2)使用共享存储时要掌握的唯一诀窍:

同步:写完再读取。(信号量、记录锁和互斥量)

(3)

shmget函数:获得一个共享存储标识符。

shmctl函数:对共享存储段执行多种操作。

shmat函数:将共享存储段连接到进程的地址空间。

shmde函数:使调用进程分离共享存储段。

(4)实例:打印特定系统中存放各种类型的数据的位置信息。

#include "apue.h"
#include <sys/shm.h>#define   ARRAY_SIZE  40000
#define MALLOC_SIZE 100000
#define SHM_SIZE    100000
#define SHM_MODE    0600    /* user read/write */char   array[ARRAY_SIZE];  /* uninitialized data = bss */int
main(void)
{int        shmid;char  *ptr, *shmptr;printf("array[] from %p to %p\n", (void *)&array[0],(void *)&array[ARRAY_SIZE]);//bssprintf("stack around %p\n", (void *)&shmid);if ((ptr = malloc(MALLOC_SIZE)) == NULL)//堆err_sys("malloc error");printf("malloced from %p to %p\n", (void *)ptr,(void *)ptr+MALLOC_SIZE);if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0)err_sys("shmget error");if ((shmptr = shmat(shmid, 0, 0)) == (void *)-1)err_sys("shmat error");printf("shared memory attached from %p to %p\n", (void *)shmptr,(void *)shmptr+SHM_SIZE);if (shmctl(shmid, IPC_RMID, 0) < 0)err_sys("shmctl error");exit(0);
}

(5)C程序的存储空间布局<163>

1)正文段:CPU执行的机器指令部分

2)初始化数据段:(数据段),包含了程序中需明确地赋初值的变量。

3)未初始化数据段:(bss段),程序开始执行之前,内核将此段中的数据初始化为0或空指针。(未初始化的全局变量)

4)栈:保存自动变量以及每次函数调用时所需保存的信息。

5)堆:进行动态存储分配。

(6)实例:相关的进程的其它实现共享存储的技术。

1)/dev/zero的存储映射                  2)线程

#include "apue.h"
#include <fcntl.h>
#include <sys/mman.h>#define  NLOOPS      1000
#define SIZE        sizeof(long)    /* size of shared memory area */static int
update(long *ptr)
{return((*ptr)++);    /* return value before increment */
}int
main(void)
{int        fd, i, counter;pid_t    pid;void    *area;if ((fd = open("/dev/zero", O_RDWR)) < 0)err_sys("open error");if ((area = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0)) == MAP_FAILED)err_sys("mmap error");close(fd);       /* can close /dev/zero now that it's mapped */TELL_WAIT();if ((pid = fork()) < 0) {err_sys("fork error");} else if (pid > 0) {            /* parent */for (i = 0; i < NLOOPS; i += 2) {if ((counter = update((long *)area)) != i)err_quit("parent: expected %d, got %d", i, counter);TELL_CHILD(pid);WAIT_CHILD();}} else {                     /* child */for (i = 1; i < NLOOPS + 1; i += 2) {WAIT_PARENT();if ((counter = update((long *)area)) != i)err_quit("child: expected %d, got %d", i, counter);TELL_PARENT(getppid());}}exit(0);
}

1)open以读写方式打开/dev/zero设备

2)调用mmap函数映射存储区fd----->void *。(优点:调用此函数创建映射之前,无需存在一个实际的文件)

3)close关闭fd

4)父子进程使用TELL_CHILD(),TELL_PARENT(),WAIT_CHILD(),WAIT_PARENT()同步(这些函数通过SIGUSR1和SIGUSR2信号进行同步)。

#include "apue.h"static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
static sigset_t newmask, oldmask, zeromask;static void
sig_usr(int signo)  /* one signal handler for SIGUSR1 and SIGUSR2 */
{sigflag = 1;
}void
TELL_WAIT(void)
{if (signal(SIGUSR1, sig_usr) == SIG_ERR)err_sys("signal(SIGUSR1) error");if (signal(SIGUSR2, sig_usr) == SIG_ERR)err_sys("signal(SIGUSR2) error");sigemptyset(&zeromask);sigemptyset(&newmask);sigaddset(&newmask, SIGUSR1);sigaddset(&newmask, SIGUSR2);/* Block SIGUSR1 and SIGUSR2, and save current signal mask */if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)err_sys("SIG_BLOCK error");
}void
TELL_PARENT(pid_t pid)
{kill(pid, SIGUSR2);        /* tell parent we're done */
}void
WAIT_PARENT(void)
{while (sigflag == 0)sigsuspend(&zeromask);   /* and wait for parent */sigflag = 0;/* Reset signal mask to original value */if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)err_sys("SIG_SETMASK error");
}void
TELL_CHILD(pid_t pid)
{kill(pid, SIGUSR1);            /* tell child we're done */
}void
WAIT_CHILD(void)
{while (sigflag == 0)sigsuspend(&zeromask);   /* and wait for child */sigflag = 0;/* Reset signal mask to original value */if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)err_sys("SIG_SETMASK error");
}

1)

int sigsuspend(const sigset_t *mask);

临时改变信号掩码并挂起,直到某信号到达。

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

此处用于改回信号掩码。

kill函数:发送信号给进程。

(7)实例:匿名存储映射。

匿名:不通过一个文件描述符与一个路径名相结合,并且创建了一个可与后代进程共享的存储区。

(8)在两个无关进程之间使用共享存储段的方法:

1)XSI共享存储函数。

2)mmap将同一文件映射至它们的地址空间。


15.10 POSIX信号量

(1)POSIX信号量接口意在解决XSI信号量接口的几个缺陷。

(2)两种形式:

1)未命名信号量:只存在于内存中,并要求能使用信号量的进程必须可以访问内存。(同一进程的线程或已映射内存)

2)命名信号量:可以通过名字访问,可以被任何已知它们名字的进程中的线程使用。

(3)POSIX信号量的Linux实现将文件映射到了进程地址空间,并且没有使用系统调用来操作各自的信号量。

(性能明显好于XSI信号量)


15.12 小结

(1)建议:使用管道和FIFO;考虑全双工管道和记录锁以避免消息队列和信号量的使用。

转载于:https://my.oschina.net/u/2463708/blog/521386

第15章 进程间通行 15.6 XSI IPC 15.7 消息队列相关推荐

  1. Linux C 进程间的IPC通信 之 消息队列(2)

    Linux C 进程间的IPC通信 之 消息队列 双向通信 代码:(进程1) 1 #include <stdio.h>2 #include <sys/msg.h>3 #incl ...

  2. Linux C 进程间的IPC通信 之 消息队列(1)

    1.消息队列 与 共享内存 1-1 消息队列  和 管道 都属于 队列结构,读完了 就被删除 不存在,但 管道 是 顺序队列 ,而 消息队列 是 链式队列 1-2  消息队列 的读和写 可设为 阻塞模 ...

  3. APUE读书笔记-第15章-进程间通信

    15.1 引言 *进程之间交换信息的方法可以经由fork或exec传送打开文件,或者通过文件系统 *进程之间相互通信的其他技术--IPC(InterProcess Communication)包括半双 ...

  4. 进程间基于消息队列的通信_Linux 进程间的通信方式

    (一)进程的概念 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就是创建一个进程,在这个 过程中伴随着资源的分配和释放,可以认为进程是一个程序的一次执行过程. (二)进程间通信的概念 ...

  5. 进程间通讯 ----- 命名管道

    进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.每个进程都有一个主线程,线程则是cpu调度的基本单位,每个进程都有自己的 ...

  6. 第15章:存储引擎和表类型#innodb的性能调整

    原贴:http://dev.mysql.com/doc/refman/5.1/zh/storage-engines.html#innodb-tuning 第15章:存储引擎和表类型 目录 15.1. ...

  7. JavaScript权威指南 第15章 网络编程 第三部分

    JavaScript权威指南 第15章 网络编程 第三部分 可伸缩矢量图形 15.7.1 在HTML中使用SVG 15.7.2 编程操作SVG 15.7.3 通过JavaScript创建SVG图片 1 ...

  8. python互斥锁原理_python并发编程之多进程1------互斥锁与进程间的通信

    一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...

  9. 【Linux】-- 进程间通讯

    目录 进程间通讯概念的引入 意义(手段) 思维构建 进程间通信方式 管道 站在用户角度-浅度理解管道 匿名管道 pipe函数 站在文件描述符角度-深度理解管道 管道的特点总结 管道的拓展 单机版的负载 ...

最新文章

  1. Spring Boot 实现扫码登录,这种方式太香了!!
  2. silverlight中的socket编程注意事项
  3. Java一致性Hash算法的实现
  4. pilt图像处理_图像处理 PIL
  5. MySQL 8.x 修改root用户密码/修改密码/重置密码/忘记密码(为了避免掉坑,值得收藏)
  6. 万圣节主题海报设计,少不了的素材
  7. Fiddler-学习笔记-远程抓包
  8. 明天要去面试...........
  9. Lua解析器管理器(封装解析器通用函数(销毁解析器,垃圾清理),通过ab包加载lua文件的加载器)
  10. 圆孔夫琅禾费衍射 matlab,信息光学基于matlab圆孔圆环夫琅禾费衍射论文副本
  11. Make menuconfig详解(转)
  12. 用磁珠隔地解决静电问题
  13. 个人域名备案详细流程(图文并茂)
  14. 637-字符串模式匹配-BF算法
  15. android 文字倾斜,TextView中文本倾斜
  16. 论文的系统 排版软件Latex
  17. 塑料壳上下扣合的卡扣设计_读书笔记-塑胶外壳卡扣设计
  18. java 页面之间传值_JSP页面间传值方法
  19. JAAS配置介绍(转载)
  20. SQL语句练习:电商数据库

热门文章

  1. 大数据、机器学习与深度学习类命令行工具汇总
  2. (流式、lambda、触发器)实时处理大比拼 - 物联网(IoT)\金融,时序处理最佳实践
  3. Oracle之分页查询
  4. 实现PHP基本安全的11条准则
  5. java 鼠标 停止工作原理,java系统级的键盘和鼠标状态
  6. 我下载的mysql解压后没有安装_mysql 解压版安装配置方法教程
  7. C 语言编程 — 运算符
  8. Sublime Text3注册激活和部分配置
  9. shell字符串截取方法
  10. wdcp 安装php_zip扩展