Linux多进程开发IV

摘要:
共享内存是进程用户空间的一部分,因此这种IPC机制需要更少的内核处理。流程组有一个生命周期。开始时间是第一个进程创建组的时间,结束时间是最后一个成员进程退出组的时间。流程组的第一个流程不需要是离开流程组的最后一个成员。会话是相关流程组的集合。新进程继承其父进程的会话ID。当在会话开始过程中第一次打开终端设备室时,建立控制终端,并且终端最多可以成为会话的控制终端。查找/2˃/dev/null|wc-l&sort˂longlist|uniq-c11。进程组,会话操作功能。
1.共享内存。允许两个或多个进程共享物理内存的同一块区域(段)。
  • 共享内存是进程用户空间的一部分,因此这种IPC机制需要更少的内核处理。一个进程将数据复制到共享内存中,那么这部分数据就会对其他所有共享同一个段的进程可用。
  • 与管道等要求发送进程将数据从用户空间的缓冲区复制到内核内存和接收进程将数据从内核内存复制进用户空间的缓冲区的做法相比,这种IPC技术速度更快。
 
2.共享内存的使用步骤。
  • 调用shmget()创建一个新共享内存段或取得一个已有的共享内存段的标识符。返回共享内存标识符。
  • 使用shmat()附上共享内存,即使该段成为调用进程的虚拟内存的一部分。
  • 此刻在程序中可以像对待其他可用内存那样对待该共享内存段。可以使用shmat()调用返回的addr值(指向进程的虚拟地址空间中该共享内存段的起点的指针)来引用共享内存。
  • 调用shmdt()分离共享内存段。
  • 调用shctl()删除共享内存段。只有当当前所有附加内存段的进程都与之分离之后内存段才会销毁。只有一个进程需要执行这一步。
 
3.相关函数。
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(ket_t key, size_t size, int shmflg);
    - 作用:创建一个新的共享内存段,或者获取一个既有的共享内存段的标识
    - key: 标识共享内存,16进制,非0
    - size: 共享内存大小
    - shmflg: 共享内存的属性,访问属性,附加属性:创建/判断共享内存是否存在,IPC_CREAT 创建;IPC_EXCL 判断共享内存是否存在,与IPC_CREAT一起使用;e.g.: IPC_CREAT | IPC_EXCL | 0664
    - 返回值:成功返回>0 表示共享内存的引用的ID,失败返回-1并设置errno
 
void *shmat(int shmid, const void *shmadd, int shmflg);
    - 作用:和当前进程进行关联
    - shmid: 共享内存的标识,由shmget返回值获取
    - shaddr: 申请的共享内存起始地址,指定NULL,由内核指定
    - shmflg: 对共享内存的操作,SHM_EXEC 执行;SHM_RDONLY 只读;0 读写权限
    - 返回值:成功返回共享内存的首地址,失败返回(void*)-1
 
int shmdt(const void *shaddr);
    - 作用:解除当前进程和共享内存的关联
    - shmaddr: 共享内存的首地址
    - 返回值:成功返回0,失败返回-1
 
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    - 作用:对共享内存进行操作。删除共享内存,共享内存要删除才会消失,创建共享内存的进程被销毁对共享内存没有影响
    - shmid: 共享内存的id
    - cmd: 要做到操作,IPC_STAT: 获取共享内存的当前状态;IPC_SET:设置共享内存的状态;IPC_RMID: 标记共享内存被销毁
    - buf: 需要设置或者获取的共享内存的属性信息,IPC_STAT: buf存储数据;IPC_SET:buf中需要初始化数据,设置到内核中;IPC_RMID:没有用,NULL
 
#include <sys/typre.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
    - 作用:根据指定的路径名,和int值,生成一个共享内存的key
    - pathname: 制定一个存在的路径
    - proj_id: int类型,系统调用只会使用其中的1个字节,0-255,一般指定一个字符'a'
 
4.共享内存相关问题。
  • 操作系统如何知道共享内存被多少进程关联?
            - 共享内存维护了一个结构体struct shmid_ds,这个结构体有一个成员 shm_nattch 记录里关联进程的个数。
  • 可不可以对共享内存多次删除? shmctl
            - 可以,因为shmctl只是标记删除共享内存,不是直接删除。只有当和共享内存关联的进程数为0时才会被真正删除。当共享内存的key位0时,表示共享内存被标记删除。
 
5.共享内存和内存映射的区别。
  • 共享内存可以直接创建,内存映射需要磁盘文件(匿名映射除外)
  • 共享内存效率更高
  • 共享内存:所有进程操作的是同一块共享内存。内存映射:每个进程在自己的虚拟地址空间中有一个独立的内存
  • 数据安全:
    • 进程突然退出:共享内存还存在,内存映射区消失
    • 运行进程的电脑死机或宕机:数据存在共享内存中的没有了;内存映射区的数据,由于磁盘文件中的数据还在,所有内存映射区的数据还存在
  • 生命周期:
    • 共享内存:进程退出,共享内存还在,标记删除(所有关联的进程数为0才会删除)或者关机。如果一个进程退出,会自动和共享内存取消关联。
    • 内存映射区:进程退出,内存映射区销毁
 
6.共享内存操作命令。
ipcs -a            打印所有进程通信方式
     -m            打印使用共享内存进行进程通信的信息
     -q            打印使用消息队列进行进程通信的信息
     -s            打印使用信号进行进程通信的信息
 
 
ipcrm -M shmkey    使用shmkey移除创建的共享内存段
ipcrm -m shmid     使用shmid移除标识的共享内存段
ipcrm -Q msgkey    使用msgkey移除创建的消息队列
ipcrm -q msgid     使用msgkey移除标识的消息队列
ipcrm -S semkey    使用semkey移除创建的信号
ipcrm -s semid     使用emkey移除标识的信号

  

7.控制终端。
  • 用户通过终端登录系统后得到shell进程,这个终端就是该shell进程的控制终端。
  • 控制终端是保存在PCB中的信息,由该shell进程启动的其它进城的控制终端也是该终端。
  • 默认情况下,每个进程的标准输入、输出、错误都指向控制终端。进程从标准输入读就是读用户键盘输入,进程往标准输出写就是输出到显示器上。
  • 在控制终端输入特殊的控制键可以给前台进程发送信号。无法给后台进程发送信号(& 结尾)。
$ tty            查看控制终端的设备
$ each $$        查看当前终端的进程号
 
8.进程组。
  • 进程组是一组相关进程的集合。
  • 进程组标识符(PGID)。
  • 进程组拥有一个生命周期,开始时间是首进程创建组的时刻,结束时间是最后一个成员进程退出组的时刻。进程组首进程无需是最后一个离开进程组的成员。
 
9.会话。
  • 会话是一组相关进程组的集合。会话首进程是创建该新会话的进程,其进程ID成为会话ID。新进程会继承其父进程的会话ID。
  • 一个会话中的所有进程共享单个控制终端。控制终端在会话首进程首次打开终端设备室被建立,一个终端最多会成为一个会话的控制终端。
  • 任一时刻,会话中其中一个进程组成为终端的前台进程组,其他进程组会成为后台进程组。只有前台进程组中的进程才能从控制终端读取数据。
  • 控制终端连接建立以后,会话首进程成为该终端的控制进程。
 
 
10.进程组、会话、控制终端之间的关系。
find / 2 > /dev/null | wc -l &
sort < longlist | uniq -c
Linux多进程开发IV第1张
Linux多进程开发IV第2张
 
11.进程组、会话操作函数。
pid_t getpgrp(void);
pid_t getpgid(pid_t pid);
int setpgid(pid_t pid, pid_t pgid);
pid_t getsid(pid_t pid);
pid_t setsid(void);
 
12.守护进程(Daemon Process  精灵进程)。
  • Linux中的后台服务进程。生存期较长,通常独立于控制终端并且周期性执行某种任务或等待处理某些发生的事件。以d结尾。
  • 特点:
    • 生命周期很长,守护进程会在系统启动时被创建并一直运行直至系统关闭。
    • 在后台运行并且不拥有控制终端。没有控制终端确保了内核永远不会为守护进程自动生成任何控制信号和终端信号。
  • e.g.: Linux的大多数服务器是守护进程实现的。Internet服务器 inetd,Web服务器 httpd 等。
 
13.守护进程的创建步骤。
  1. 执行一个fork(),父进程退出,子进程继续执行。(必须)
  2. 子进程调用setid()开启一个新的会话。(必须)
  3. 使用umask(0)清除进程的umask以确保守护进程创建文件和 目录时拥有权限。
  4. 修改进程的当前工作目录,改为根目录(/)。
  5. 关闭守护进程从父进程继承而来的所有打开的文件描述符。
  6. 关闭文件描述符0,1,2之后,守护进程打开/dev/null 并使用dup2()使所有这些描述符指向这个设备。
  7. 核心业务逻辑。(必须)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

免责声明:文章转载自《Linux多进程开发IV》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Android系统编程入门系列之广播接收者BroadcastReceiver实现进程间通信jndi和jta事务下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

虚拟化之KVM virsh常用命令篇

1,查看运行的虚拟机 virsh list 2,查看所有的虚拟机(关闭和运行的虚拟机) virsh list --all 3,连接虚拟机 virsh console +域名(虚拟机的名称) 4,退出虚拟机 ctrl+] 5,关闭虚拟机 5.1    virsh shutdown +域名   这个时候我在virsh list发现 test02这个虚拟机还是在...

Linux 的字符串截取很有用。有八种方法。

假设有变量 var=http://www.aaa.com/123.htm 1. # 号截取,删除左边字符,保留右边字符。 echo ${var#*//} 其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符 即删除 http:// 结果是 :www.aaa.com/123.htm 2. ## 号截取,删除左...

Ubuntu 针对 SSD 的优化方案

. . . . . 首先看下 LZ 的分区情况: >$ sudo fdisk -l Disk /dev/sda: 120.0 GB, 120034123776 bytes 255 heads, 63 sectors/track, 14593 cylinders, total 234441648 sectors Units = sectors...

在Linux中监视IO性能

dd命令 iostat命令 理解iostat的各项输出 iostat的应用实例 附:在Windows中监视IO性能 延伸阅读 dd命令 dd其实是工作于比较低层的一个数据拷贝和转换的*nix平台的工具,但是因为dd命令支持*nix平台的一些特殊设备,因此我们可以利用dd命令的这个特性来简单的测试磁盘的性能。 先说一下两个相关的特殊设备...

把GCC的编译信息重定向到一个文件

最近在Linux下进行编程,很多写好的代码要进行编译。在链接很多文件的时候,经常会出现很多的错误,而Linux下终端显示是有限的,因此每次调试的时候如果错误太多就会很不方便。如果使用简单的管道重定向如下: gcc -c test.c > error.txt 这种方式是不行的。   我上网找相关的方法,发现很多人在问,找到的信息也比较少。有些方法甚至要...

Linux获取系统时间

一、查看和修改Linux的时区 1. 查看当前时区命令 : "date -R"2. 修改设置Linux服务器时区方法 A命令 : "tzselect"方法 B 仅限于RedHat Linux 和 CentOS命令 : "timeconfig"方法 C 适用于Debian命令 : "dpkg-reconfigure tzdata"3. 复制相应的时区文件,替...