1.共享内存:
概念:共享内存,就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为一段物理内存。进程可以将同一段物理内存连接到他们自己的地址空间中,所有的进程都可以访问共享内存中的地址。如果某个进程向共享内存写入数据,所做的改动将立刻影响到可以访问到同一共享内存的其他进程
原理:在Linux中,每个进程都有属于自己的进程控制块(PCB)和地址空间(AddrSpace),并且都有一个与之对应的“页表”,负责将进程的虚拟地址和物理地址进行映射,通过内存管理单元(MMU)。两个不同的虚拟地址通过页表映射到物理空间的同一区域,这个区域就是共享内存区域。
函数和指令:
(1)查看系统中的共享存储段
ipcs -m
(2)删除系统中的共享存储段
ipcrm -m [shmid]
(3)shmget()创建共享内存
int shmget(key_t key, size_t size, int shmflg);
入参:
(1).由ftok生成的key标识,标识系统的唯一IPC资源
(2).需要申请共享内存的大小
(3).访问权限(和文件权限是一致的)
如果共享内存不存在,则需要使用IPC_CREAT或IPC_EXCL创建共相册i村
如果共享内存已存在,可以使用IPC_CREAT或直接传0,获得共享内存
返回值:
成功则返回一个新建或者已存在的共享内存标识符,取决于shmflg的参数
失败返回-1
(4)shmat()挂接共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg);
入参:
(1).共享存储段的标识符
(2).shmaddr=NULL,则存储段连接到由内核选择的第一个可以挂接的地址上(推荐使用)
(3).指定SHM_RDONLY,则以只读方式连接此段,0是可以以读写方式连接此段
返回值:
成功返回共享存储段的指针(虚拟地址)
失败返回-1
(5)shmdt()去关联共享内存
当一个进程不需要共享内存的时候,就需要去关联,该函数并不删除指定的内存区,而是将之前用shmat函数连接好的共享内存区脱离目前的进程
int shmdt(const void *shmaddr);
入参:
连接以后返回的地址
返回值:
成功返回0
失败返回-1
(6)shmct()销毁共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
入参:
(1).共享存储段标识符
(2).指定的执行操作,设置为IPC_RMID时表示可以删除共享你内存
(3).buf:设置NULL即可
返回值:
成功返回0
失败返回-1
2.进程组和会话
概念:
进程组,每个进程组有一个领头的进程。进程组是一个或多个进程的集合,通常他们与一组作业相关联,可以接受来自同一个终端的各种信号
每个进程组都有唯一的进程组ID(整数,也可以存放在pid_t类型中)
进程组由进程组ID来唯一标识,除了进程号(PID)外,进程组ID也是一个进程的必备属性之一
#include<unistd.h>
pid_t getpgrp(void);
返回值是进程的进程组ID
创建会话:
创建一个会话需要注意一下6点注意事项:
1. 调用进程不能是进程组组长,该进程会变成新会话的首进程
2. 该进程成为一个新进程组的组长进程
3. 需要有root权限(ubuntu中是不需要的)
4. 新会话丢弃原有的控制终端,该会话没有控制终端
5. 该调用进程是组长进程,则出错返回
6. 建立新会话时,先调用fork,父进程终止,子进程调用setsidu
getsid函数:获取进程所属会话的id
pid_t getsid(pid_t pid);
返回值:
成功:返回调用进程的会话ID
失败:-1,设置error
入参:
pid为0表示查看当前进程session ID
ps ajx
查看系统中进程的命令
参数a表示不仅当前用户的进程,也列出所有其他用户的进程
参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程
参数j表示列出与作业息息相关的信息,小组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程
setsid函数:创建一个会话,并且以自己的ID设置进程组ID,同时也是新会话的ID
pid_t setsid(void);
返回值:
成功:返回调用进程的会话ID
失败:-1,设置errno
3.守护进程:
概念:守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务,很多守护进程在系统引导的时候启动,并且一直运行到系统关闭,另一些只在需要的时候才启动,完成任务以后会自动结束
创建步骤:
1. 创建子进程, 父进程退出
所有工作在子进程中进行形式上脱离了控制終端
2. 在子进程中创建新会话
setsid)函数
使子进程完全独立出来,脱离控制
3. 改变当前目录(比如为根目录)
chdir()函数
防止占用可卸载的文件系统
也可以换成其它路径
4.重设文件权限掩码
umask()函数
防止继承的文件创建屏蔽宇拒绝某些权限
增加守护进程灵活性
5.关闭文件描述符。
继承的打开文件不会用到,浪费系统资源,无法卸载
6. 开始执行守护进程核心工作守护进程退出处理程序模型
4.信号:
概念:现代战争中的信号弹
1. 简单
2. 不能携带大量信息
3. 满足某个特设条件才发送。
信号是信息的载体, Linux/UNIX 环境下,古老、经典的通信方式,现下依然是主要的通信手段。
Unix 早期版本就提供了信号机制,但不可靠,信号可能丢失。 Berkeley 和 AT&T 都对信号模型做了
更改,增加了可靠信号机制。但彼此不兼容。 POSIX.1 对可靠信号例程进行了标准化
机制:
信号机制是一种使用信号来进行进程之间传递消息的方法,信号的全称为 == 软中断信号 == ,简称软中断。信号的本质是软件层次上对中断的一种模拟(软中断)。它是一种异步通信的处理机制,事实上,进程并不知道信号何时到来。
比如: A 给 B 发送信号, B 收到信号之前执行自己的代码,收到信号后,不管执行到程序的什么位置,都要暂停运行,去处理信号,处理完毕再继续执行。
信号的特质 : 由于信号是通过软件方法实现,其实现手段导致信号有很强的延时性。但对于用户来说,这个延迟时间非常短,不易察觉。
每个进程收到的所有信号,都是由内核负责产生和发送的,由内核处理。
信号是软件层面上的 “ 中断 ” 。一旦信号产生 , 无论程序执行到什么位置,必须立即停止运行,处理信号,
处理结束,再继续执行后续指令。