当前位置: 首页 > news >正文

Linux/AndroidOS中进程间的通信线程间的同步 - POSIX IPC

1 什么是POSIX?

POSIX(Portable Operating System Interface)即可移植操作系统接口,它是IEEE为要在各种UNIX操作系统上运行软件,而定义API的一系列标准的总称。以下为你展开介绍:

  • 产生背景:在20世纪80年代,UNIX操作系统存在着多种不同的版本和实现,这些版本之间存在着差异,这给应用程序的移植和开发带来了很大的困难。为了解决这个问题,IEEE计算机协会开始制定POSIX标准,旨在定义一套通用的操作系统接口,使得应用程序能够在不同的UNIX系统上实现高度的可移植性。
  • 主要内容:POSIX标准涵盖了进程管理、文件系统、网络通信、输入输出等多个方面的接口定义。例如,在进程管理方面,定义了创建、终止、等待进程等函数接口;在文件系统方面,规定了文件的打开、关闭、读写等操作的接口规范。
  • 应用场景:POSIX标准广泛应用于各种UNIX类操作系统,如Solaris、FreeBSD、Linux等。许多企业级应用程序、网络服务器软件、数据库管理系统等都是基于POSIX标准开发的,从而确保了这些软件在不同的UNIX系统上具有一致的行为和性能。
  • 意义和影响:POSIX标准的出现,极大地促进了UNIX系统的发展和应用。它使得软件开发者可以更加专注于应用程序的功能实现,而不必过多地考虑不同操作系统之间的差异。同时,POSIX标准也为操作系统的标准化和规范化奠定了基础,推动了操作系统技术的不断进步。

除了UNIX类操作系统,现在也有一些其他操作系统为了实现更好的兼容性和可移植性,也部分支持POSIX标准,使得基于POSIX开发的软件能够在这些系统上运行。

2 POSIX标准是如何发展和演变的?

POSIX标准的发展和演变是一个长期且持续的过程,以下是其主要的发展阶段和关键节点:

  1. 早期的制定(20世纪80年代):20世纪80年代初,IEEE计算机协会下属的一个委员会开始致力于开发一套统一的UNIX系统接口标准,以解决当时UNIX系统版本众多且互不兼容的问题。1983年,IEEE成立了POSIX工作组(IEEE Project 1003),正式启动POSIX标准的制定工作。1988年,POSIX.1标准(IEEE Std 1003.1-1988)发布,它定义了基本的操作系统服务接口,包括进程管理、文件和目录操作、信号处理等,为应用程序在不同UNIX系统间的移植提供了基础。
  2. 扩展与完善(20世纪90年代):1990年,POSIX.2标准发布,该标准主要关注shell和工具,定义了shell命令语言、实用程序的接口和行为规范,如常见的文本处理工具、文件操作工具等。随着网络技术的发展,1995年发布了POSIX.4标准,将实时操作系统功能和交互式用户应用程序接口集成到POSIX标准中,增加了对实时性、异步I/O、消息队列等功能的支持,以满足实时系统和嵌入式系统的需求。
  3. 国际化与整合(20世纪90年代末 - 21世纪初):为了适应全球不同地区和语言的需求,POSIX标准引入了国际化相关的内容,支持多字节字符集、区域设置等功能,使软件能够更好地在不同语言环境下运行。1999年,IEEE将多个POSIX子标准进行整合和修订,发布了IEEE Std 1003.1-1999标准,进一步完善了标准内容,并对一些接口进行了优化和澄清。
  4. 持续更新与适应新技术(21世纪以来):进入21世纪,随着计算机技术的快速发展,新的硬件平台、软件架构和应用场景不断涌现,POSIX标准也持续更新。例如,对多核处理器、云计算、物联网等新兴技术的支持逐渐被纳入标准的考虑范围。同时,POSIX标准与其他国际标准组织(如ISO)合作,使标准在全球范围内得到更广泛的认可和应用。ISO将POSIX标准采纳为国际标准ISO/IEC 9945,进一步推动了POSIX标准的国际化进程。在这一时期,POSIX标准不断修订和更新,以保持其在现代操作系统环境中的适用性和先进性。

如今,POSIX标准仍然在不断发展和演变,以适应不断变化的技术环境和应用需求。 其发展历程反映了操作系统技术的进步以及对软件可移植性、兼容性和功能性的持续追求。

3 Linux/Android遵循POSIX标准

POSIX.1b 实时扩展定义了一组 IPC 机制,这些 IPC 机制被统称为 POSIX IPC。这三种 POSIX IPC机制具体如下。

  • 消息队列可以用来在进程间传递消息。消息边界被保留了下来,这样读者和写者就以消息为单位(与管道提供的无分隔符的字节流是不同的)进行通信了。POSIX 消息队列允许给每个消息赋一个优先级,这样在队列中优先级较高的消息会排在优先级较低的消息前面。
  • 信号量允许多个进程同步各自的动作。POSIX 信号量是一个由内核维护的整数,其值永远都不会小于 0。POSIX信号量在用法上很简单:它们是逐个分配的,并且在单个信号量上只能使用两个操作来将信号量的值加 1 或减 1。
  • 共享内存使得多个进程能够共享同一块内存区域。POSIX共享内存提供了一种快速 IPC。一个进程一旦更新了共享内存之后,所发生的变更立即对共享同一区域的其他进程可见。

本文将对各个 POSIX IPC 工具进行概述,并着重介绍它们的共有特性。

4 API概述

三种 POSIX IPC 机制拥有很多共有特性。下表对它们的 API 进行了总结。
在这里插入图片描述

4.1 IPC 对象名字

要访问一个 POSIX IPC 对象就必须要通过某种方式来识别出它。在 Linux 上,POSIX 共享内存和消息队列对象的名字的最大长度为 NAME_MAX(255)个字符,而信号量的名字的最大长度要少 4 个字符,这是因为实现会在信号量名字前面加上字符串 sem. 。

4.2 创建或打开 IPC 对象

每种 IPC 机制都有一个关联的 open 调用(mq_open()、sem_open()以及 shm_open()),它与用于打开文件的传统的 UNIX open()系统调用类似。给定一个 IPC 对象名,IPC open 调用会完成下列两个任务中的一个。

  • 使用给定的名字创建一个新对象,打开该对象并返回该对象的一个句柄。
  • 打开一个既有对象并返回该对象的一个句柄。

IPC open 调用返回的句柄与传统的 open()系统调用返回的文件描述符类似——它在后续的调用中被用来引用该对象。

IPC open 调用返回的句柄的类型依赖于对象的类型。对于消息队列来讲返回的是一个消息队列描述符,其类型为 mqd_t。对于信号量来讲,返回的是一个类型为 sem_t *的指针。对于共享内存来讲返回的是一个文件描述符。

所有 IPC open 调用都至少接收三个参数——name、oflag 以及 mode,如下面的shm_open()调用所示:

fd = shm_open("/mymem", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);

这些参数与传统的 UNIX open()系统调用接收的参数类似。name 参数标识出了待创建或待打开的对象。oflag 参数是一个位掩码,在这个参数中至少可以包含下列几种标记。

  • O_CREAT
    如果对象不存在,那么就创建一个对象。如果没有指定这个标记并且对象不存在,那么就返回一个错误(ENOENT)。
  • O_EXCL
    如果同时也指定了 O_CREAT 并且对象已经存在,那么就返回一个错误(EEXIST)。这两步——检查是否存在和创建——是原子操作。这个标记在不指定 O_CREAT 时是不起作用的。

根据对象的类型,oflag 还可能会包含 O_RDONLY、O_WRONLY、 O_RDWR 这三个值中的一个,其含义与它们在 open()中含义相同。

剩下的参数 mode 是一个位掩码,它指定了在对象被创建时(即指定了 O_CREAT 并且对象不存在)施加于新对象之上的权限。mode 参数能取的值与其在文件上的取值一样。与 open()系统调用一样,mode 中的权限掩码会根据进程的 umask取掩码。新 IPC对象的所有权和组所有权将根据发起这个 IPC open 调用的进程的有效用户 ID 和组 ID 来确定。

4.3 关闭 IPC 对象

对于 POSIX 消息队列和信号量来讲,存在一个 IPC close 调用来表明调用进程已经使用完该对象,系统可以释放之前与该对象关联的所有资源了。POSIX 共享内存对象的关闭则是通过使用 munmap()解除映射来完成的。

IPC 对象在进程终止或执行 exec()时会自动被关闭。

4.4 IPC 对象权限

IPC 对象上的权限掩码与文件上的权限掩码是一样的。访问一个 IPC 对象的权限与访问文件的权限是类似的,但对于 POSIX IPC 对象来讲,执行权限是没有意义的。

4.5 IPC 对象删除和对象持久性

与打开文件一样,POSIX IPC 对象也有引用计数——内核会维护对象上的打开引用计数
每个 IPC 对象都有一个对应的 unlink 调用,其操作类似于应用于文件的传统的 unlink()系统调用。unlink 调用会立即删除对象的名字,然后在所有进程使用完对象(即当引用计数等于 0 时)之后销毁该对象。

  • 对于消息队列和信号量来讲,这意味着当所有进程都关闭对象之后对象会被销毁;
  • 对于共享内存来讲,当所有进程都使用 munmap()解除与对象之间的映射关系之后就会销毁该对象。

当一个对象被断开链接之后,指定同一个对象名的 IPC open 调用将会引用一个新对象(在不指定 O_CREAT 时会失败)。
POSIX IPC 对象拥有内核持久性。对象一旦被创建,就会一直存在直到被断开链接或系统被关闭。这样一个进程就能够创建一个对象、修改其状态,然后退出并将对象留给在后面某个时刻启动的一些进程访问。

4.6 通过命令行列出和删除 POSIX IPC 对象

Linux系统上, IPC 对象是在一个挂载在根目录(/)下某处的真实或虚拟文件系统中实现的,因此可以使用标准的 ls 和rm 命令来列出和删除 IPC 对象。
在 Linux 上,POSIX IPC 对象位于挂载在设置了粘滞位的目录下的虚拟文件系统中。这个位是一个受限的删除标记,设置该位表示非特权进程只能够断开它自己拥有的POSIX IPC 对象的链接。

4.7 在 Linux 上编译使用 POSIX IPC 的程序

在 Linux 上,使用 POSIX IPC 机制的程序必须要与实时库 librt 链接起来,这可以通过在cc 命令中指定–lrt 选项来完成。

4.8 何为粘滞位

在Linux系统中,粘滞位(sticky bit)是文件和目录的一种特殊权限位。它有着独特的作用和表现,以下为你详细介绍:

  1. 基本概念:粘滞位是文件权限中的特殊标志之一,在传统的读(r)、写(w)、执行(x)权限基础上额外存在。可以使用 ls -l 命令查看目录或文件权限时,若其他用户的执行权限位置上显示为 t(本来执行权限位是 x,有粘滞位时显示 t,若没有执行权限,显示为 T),就表示该目录或文件设置了粘滞位。
  2. 作用原理:对于普通文件,粘滞位作用不大。但对于目录而言,粘滞位的作用非常重要。当一个目录设置了粘滞位后,只有该目录的所有者、文件的所有者或者超级用户(root)才有权删除或重命名该目录下的文件。即使其他用户对该目录有写入权限,也不能删除或重命名不属于自己的文件。例如,在 /tmp 目录(通常都设置了粘滞位)下,多个用户都可以创建文件,但每个用户只能删除或重命名自己创建的文件,而不能删除其他用户的文件。这样可以防止用户误删或恶意删除他人的文件,保证了目录中文件的安全性。
  3. 设置和取消:可以使用 chmod 命令来设置或取消粘滞位。例如,要给目录 test 设置粘滞位,可以使用命令 chmod o+t test;如果要取消 test 目录的粘滞位,则使用命令 chmod o-t test。其中,o 表示其他用户,+t 表示添加粘滞位,-t 表示去除粘滞位。
  4. 应用场景:除了 /tmp 目录外,一些公共可写的目录(如共享的临时文件存储目录等)也可能会设置粘滞位,以确保在多用户环境下文件的安全性和管理的有序性。

粘滞位是Linux系统中用于增强目录安全性和文件管理的重要权限机制,在多用户环境中起着关键作用。

相关文章:

  • 【MongoDB篇】MongoDB的事务操作!
  • LeetCode 1128. 等价多米诺骨牌对的数量 题解
  • C++ STL 基础与多线程安全性说明文档
  • Visual Studio 快捷键更改和设置
  • 使用ip池后,爬虫还被封,是什么原因呢?
  • Zoho在2025:三个支点和一个新故事
  • 数据管理平台是什么?企业应如何做好数据化管理?
  • MySQL数据库中篇
  • 【STM32项目实战】一文了解单片机的SPI驱动外设功能
  • Vue3 中用 canvas 封装抽奖转盘组件:设定中奖概率及奖项图标和名称
  • LeetCode:二叉树的中序遍历
  • 【SpringBoot】SpringBoot中使用AOP实现日志记录功能
  • [HOT 100] 2646. 最小化旅行的价格总和
  • 前景理论——AI与思维模型【95】
  • 量子跃迁:破解未来计算的“时空密码”​
  • 分库分表后复杂查询的应对之道:基于DTS实时性ES宽表构建技术实践
  • enum4linux:渗透测试中的Windows信息收割机!全参数详细教程!Kali Linux教程!
  • Cursor 被封解决方案
  • MySQL 常用函数分类
  • Leetcode 刷题记录 08 —— 链表第二弹
  • 又一日军“慰安妇”制度受害者去世,大陆登记在册幸存者仅剩7人
  • 同观·德国|默茨当总理后,能否带领德国在欧盟“说了算”?
  • 央行:5月8日起7天期逆回购操作利率由此前的1.50%调整为1.40%
  • 哈马斯官员:进一步停火谈判毫无意义
  • 超越关税陷阱,不遗余力塑造产业的长期竞争力
  • 美国得克萨斯州发生5.4级地震,震源深度10千米