目录
1、管道
2、消息队列
(1)ftock()--创建IPC的键值KEY
(2)获取消息队列ID
(3)发送和接收消息
(4)设置或者获取消息队列的相关属性
3、共享内存
(1)获取共享文件得ID--shmget()
(2)对共享内存进行映射--shmat()或解除映射--shmdt()
(3)获取或设置共享内存的相关属性
4、信号量
(1)概念引入
(2)信号量的创建-semget()
(3)获取或设置信号量的属性
(4)信号量的P/V操作
5、守护进程
(1)查看系统常见的系统守护进程
(2)脏页面
(3)守护进程的特点
(4)Linux守护进程在操作系统中扮演着重要的角色,其存在的主要有以下几个意义
(5)守护进程的启动方法
(6)创建守护进程的标准思路
(7)初始化一个守护进程
进程的通信方式一共有6种,分别是:管道、信号、消息队列、共享内存、信号量组和套接字。其中前五种属于单个主机内进程之间的通信方式;套接字属于多个主机之间的进程之间的通信。
1、管道
- 读者:持有文件可读权限的描述符的进程
- 写者:持有文件可写权限的描述符的进程
2、消息队列
system-V IPC包含消息队列、共享内存、信号量组,称为系统5,它们都需要一个键值key来唯一标识,它们被创建之后,不会因为进程的退出而消失,除非调用特殊函数或命令删除。
IPC相关命令:
- (1)查看消息队列:ipcs -q key或ID
- (2)查看共享内存:ipcs -m key或ID
- (3)查看信号量组:ipcs -s key或ID
- (4)查看所有IPC对象:ipcs -a
- (5)删除指定的消息队列:ipcrm -q MSG_ID或ipcrm -Q msg_key
- (6)删除指定的共享内存:ipcrm -m SHM_ID或ipcrm -M shm_key
- (7)删除指定的信号量组:ipcrm -s SEM_ID或ipcrm -S sem_key
(1)ftock()--创建IPC的键值KEY
- pathname可以是具体的文件(磁盘),也可以是指定的路径(内存)
- pathnaem指定路径:设置IPC通信内存资源位置
- pathname指定文件:设置IPC通信内存(闪存)资源的位置,稳定性没有指定路径强
- ftok()创建的key值受两个形参的影响,可以通过改变proj_id来创建不同的key值
- 如果key值不同则创建的消息队列不同,将导致进程间无法通信
- 如果key值相同则创建的消息队列相同,确保两个进程使用同一个消息队列,才可以实现通信。
- Linux的ftock()函数可以生成2^32个不同的key值,创建大概40亿个不同的key值。
- ftock()生成的键值是一个32位整数,它将文件名的设备号、文件的inode号以及项目表示符组合起来生成一个唯一的key值。
(2)获取消息队列ID
消息队列只有读写权限,没有执行权限
777: 1 1 0--> 读 写 执行
- 对创建者拥有的权限:第一个7
- 对同组用户的权限 :第二个7
- 对不同组用户的权限 :第三个7
- 进程A想要与进程B想要通过消息队列进行通信,一定要使用相同的消息队列
- 相同的消息队列:相同的消息队列ID、相同的键值KEY,相同的IPC路径和IPC标识
- 程序退出时,创建的IPC依然存在,不会释放内存资源
(3)发送和接收消息
发送者:
-
-
- 获取消息队列的ID
- 将数据放入一个附有标识的特殊的结构体,发送给消息队列
-
接收者:
-
-
- 获取消息队列的ID
- 将指定标识的消息读出。
-
当发送者与接收者都不再使用消息队列时,及时删除它以释放系统资源
- msgflag设置为0,采用默认模式
- 系统提供模板结构体,用于存放发送的消息以及规定消息通信的格式
- 在System-V IPC中,mtype的取值范围是从1~LONG_MAX(即2147483647),这是因为被定义为long int类型,其最大值由LONG_MAX定义。在实际使用中,mtype可以取的最大值是2147483647,即约21亿。
- 发送消息:将自己的消息标识直接赋值到模板结构体的mtype
- 接收消息:把自己要的消息标识设置填到msgrcv的第4个参数
(1)发送和接收消息时,消息需要被组织成以下形式: struct msgbuf { long mytype; //消息的标识,用来区分不同类型的消息,占据消息的头部 char mtext[1]; //消息的正文 //下面可以自己定义要发送的成员的数据变量 int age[10]; int sex[10]; }
(2)消息的标识可以是任意长整型数值,但不能是0L
(3)参数msgsz是消息种正文的大小,不包含消息的标识
(4)设置或者获取消息队列的相关属性
删除消息队列的调用如下: if(msgctl(msg_id,IPC_RMID,NULL)==-1) { perror("msgctl failed"); return -1; }
总结:消息队列是管道的进阶版本,与管道不同的是,可以通过键值key将信息发送给指定的进程
消息队列的特点:因为消息队列中有消息标识用来区分发送和接收消息,所以支持“多”对“多”
3、共享内存
通信效率最高的IPC,直接裸露一块内存空间进行数据传输,常用于上传和下载大数据。共享内存不可以单独使用,而是需要配合信号量、互斥锁等协调机制,使得同意快物理内存多次映射到不同得进程虚拟空间之中,相当于多个进程得虚拟内存空间部分重叠在一起。
查看系统页存储大小的命令 getconf PAGESIZE 注意:共享内存的大小如果不是页的倍数,也会无法设置进去
使用共享内存得一般步骤:
- 获取共享内存对象得ID
- 将共享内存映射到本进程虚拟内存空间的某个区域
- 当不再使用时,解除映射关系
- 当没有进程再需要这块共享内存时,删除它
(1)获取共享文件得ID--shmget()
大页面:指内核为了提高程序性能,对内存实行分页管理时,采用比默认尺寸(4KB)更大的分页,来减少缺页中断。Linux内核支持以2MB位物理页面的基本单位。
(2)对共享内存进行映射--shmat()或解除映射--shmdt()
注意:
- 共享内存只能以只读或只写方式进行映射,无法以只写方式映射
- 第二个参数shmaddr一般为NULL,让系统自动寻找合适的地址。
- 解除映射之后,进程不能再允许访问SHM
- 共享内存是IPC中效率最高的机制。保护性不高
- 开发中,用设置共享内存大小是PAGESIZE的倍数,但是,如果第一次设置小于或者大于PAGESIZE也可以正常设置
- 共享内存设置大小是在第一次(创建的那一次)就确定了,第二次调用函数中的第二个参数比第一次的小,默认使用第一次的大小空间,第二次比第一次大,获取ID失败
(3)获取或设置共享内存的相关属性
4、信号量
信号量与信号集不一样,起到一个同步互斥的作用(修改数据的时候要互斥,读取数据的时候可以同步)
(1)概念引入
资源监视器+数据操作控制器(获取资源数据值),资源控制器。
资源:有限的,不够让进程进入睡眠状态,需要我们初始化资源的值。
共享资源:多个进程或线程有可能同时访问的资源(变量、链表、文件等)称为共享资源,也叫做临界资源。
临界区:访问共享资源的代码称为临界代码,这些代码区域被称为临界区。
P操作:程序进入临界区之前必须对资源进行申请,这个动作称为P操作。
V操作:程序离开临界区之后必须释放相应资源,这个动作称为V操作。
Linux中用到的信号量有三种:ststem-V信号量、POSIX有名信号量和POSIX无名信号量。用来表征一种资源的数量,当多个进程或者线程争夺这些稀缺资源的时候,信号量用来保证它们合理的、秩序的使用这些资源,而不陷入逻辑谬误中。
(2)信号量的创建-semget()
信号量用来监视资源:元素就是资源的种类。
(3)获取或设置信号量的属性
1、元素资源值设置: union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; }; 步骤: (1)union semun xxx; (2)xxx.val=你要设置的元素值 (3)semctl(sem_id,o,SETVAL,xxx); //0: 车 1:车位 (4)数组存放资源值 xxx[2] (5)xxx[0] = 0 : 车 (6)xxx[1] = 3 :车位 2、元素资源值获取 保存获取到的元素值 = semctl(sem_id,0,GETVAL); 数组存放资源值 xxx[2] xxx[0] : 0 :车 xxx[1] : 3 :车位
创建信号量还受到以下系统信息的影响:
- SEMMNI:系统中信号量的总数最大值
- SEMMSL:每个信号量中信号量元素的个数最大值
- SEMMNS:系统所有信号量中的信号量元素的总数最大值
- 在Linux中,以上信息在/proc/sys/kernel/sem可以查看
(4)信号量的P/V操作
5、守护进程
(1)查看系统常见的系统守护进程
使用命令【ps -ef】可以查看系统的守护进程
系统守护进程常见的执行任务:
- kswapd:内存换页守护进程。支持虚拟内存子系统在一段时间后把“脏页面”慢慢的回写磁盘来回收这些页面的内存资源
- flush操作:在可用内存达到设置的最小阈值时将脏页面写入磁盘
- jdb(内核模块):帮助实现ext4文件系统中的日志功能
(2)脏页面
(3)守护进程的特点
所有守护进程都没有控制终端,其终端名字被设置成问号(即tty那一列显示 ? ) 用户层守护进程缺少控制终端可能是守护进程调用了setsid造成的。setid当守护进程脱离当前登录会话,由于会话和控制终端具有独占性所以控制终端也脱离了。 因为调用了setid,大多数用户层守护进程都是进程组组长以及会话的首进程。 注意用户层守护进程的父进程是init进程。
(4)Linux守护进程在操作系统中扮演着重要的角色,其存在的主要有以下几个意义
- 服务持久性:守护进程通常是为了提供长期运行的服务而设计的,它们能够在系统启动时自动启动,并持续运行在后台,直到系统关闭或显式停止。
- 资源管理:守护进程可以管理系统资源的分配和使用,例如网络服务、数据库服务等。它们通常设计为高效利用系统资源,以提供稳定和持续的服务。
- 任务调度:某些守护进程可能会负责定期执行特定的任务或作业,例如定时备份、日志清理等,这有助于自动化和简化系统管理。
- 响应用户请求:守护进程可以响应用户请求,例如Web服务器可以处理来自客户端的HTTP请求,数据库服务可以处理查询请求等,从而使得多个用户可以同时访问和利用系统资源。
- 提高系统安全性:通过守护进程,系统管理员可以限制和控制用户对系统的访问和操作,实现更高级别的安全性措施,例如访问控制、身份验证等。
- 日志记录与故障排除:守护进程通常会生成详细的日志记录,用于追踪系统运行状况和故障排除。这些日志对于分析和解决问题非常有帮助。
- 系统性能优化:合理设计的守护进程可以通过优化资源使用和处理效率,帮助提升系统整体性能,确保系统在高负载和长时间运行时仍然稳定和可靠。
总的来说,Linux守护进程是支持系统长期运行和提供服务的关键组成部分,它们通过后台运行、资源管理、任务调度和响应用户请求等功能,有效地增强了系统的功能性、安全性和稳定性。
(5)守护进程的启动方法
① 在系统启动的阶段,大多数系统的守护进程都是由系统初始化脚本启动的。这些脚本文件一般在/etc 或者 /etc/rc开头的的某个目录中,一般都是用超级用户权限运行的。
② 某些常见的网络服务器也是通过这些脚本启动守护进程的inetd、wed服务器
③ 内核守护进程以无控制中终端的模式启动。
(6)创建守护进程的标准思路
① 调用umask将文件模式创建的掩码设置为0。
② 调用fork函数然父进程exit, 使得
③ 调用setsid函数创建一个会话,输出信息 使子进程成为新会话的首进程 使子进程成为进程组组长 使子进程没有控制终端
④ 将当前工作目录更改为根目录 /dexx/xxx/x
⑤ 关闭不在需要的文件描述符 守护进程并不与终端设备相关联,所以其输出无处显示, 也无发通过交互式获取用户哪里接受输入
(7)初始化一个守护进程
Linux系统守护进程基本实现_开发板守护进程在哪里启动-CSDN博客