系统编程-02进程间通信

目录

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 注意:共享内存的大小如果不是页的倍数,也会无法设置进去

使用共享内存得一般步骤:

  1. 获取共享内存对象得ID
  2. 将共享内存映射到本进程虚拟内存空间的某个区域
  3. 当不再使用时,解除映射关系
  4. 当没有进程再需要这块共享内存时,删除它

(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博客

  • 27
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉辰梦凡星

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值