UNPV2 学习:System V IPC 章节学习问题记录

环境信息

OS:debian11
kernel:linux kernel 5.15

linux 环境测试时附录源代码修改

#ifndef MSG_R
#define SVMSG_MODE (FILE_MODE)
#else
#define	SVMSG_MODE	(MSG_R | MSG_W | MSG_R>>3 | MSG_R>>6)
#endif

linux 上 System V IPC 实现的一些特点

查看 System V IPC 占用率

可以使用 lspic 来查询 System V IPC 状态信息,示例如下:

RESOURCE DESCRIPTION                                              LIMIT USED  USE%
MSGMNI   Number of message queues                                 32000   10 0.03%
MSGMAX   Max size of message (bytes)                               8192    -     -
MSGMNB   Default max size of queue (bytes)                        16384    -     -
..................................................................................

缺省的限制为 32000,lspic 能够显示消息队列的使用情况,在上面的实例中,有 10 个消息队列被使用,占用率约为 0.03%。

System V IPC 的释放

创建 System V IPC 的进程退出时内核不会回收 ipc,除非主动调用释放函数。ipc id 泄露完了后,再次尝试创建会报如下错误:

msgget error: No space left on device

lsipc 能够看到如下内容:

[longyu@debian:12:36:21] svmsg $ lsipc
RESOURCE DESCRIPTION                                              LIMIT  USED    USE%
MSGMNI   Number of message queues                                 32000 32000 100.00%
.....................................................................................

32000 个 id 已经被分配,占用率为 100%。
man msgget 得到如下描述信息:

MSGMNI System-wide limit on the number of message queues.  Before Linux 3.19, the default value for this limit was calculated using  a  formula
              based  on  available  system  memory.  Since Linux 3.19, the default value is 32,000.  On Linux, this limit can be read and modified via
              /proc/sys/kernel/msgmni.

msgmni 可以动态修改,允许修改的值有限定,比 32000 小可以正常配置,比 32000 大,需要符合特定的规律才能设定。

[longyu@debian:12:54:17] kernel $ sudo su  -c   'echo 32600 > msgmni '
[longyu@debian:12:54:32] kernel $ cat ./msgmni 
32600

921271566
1102226159

linux 内核代码中对 System V IPC id 的描述信息

 18 /*
 19  * The IPC ID contains 2 separate numbers - index and sequence number.
 20  * By default,
 21  *   bits  0-14: index (32k, 15 bits)
 22  *   bits 15-30: sequence number (64k, 16 bits)
 23  *
 24  * When IPCMNI extension mode is turned on, the composition changes:
 25  *   bits  0-23: index (16M, 24 bits)
 26  *   bits 24-30: sequence number (128, 7 bits)
 27  */

linux 内核的 IPC ID 由 index 与 sequence number 两部分数值拼接而成。默认配置下这两部分数值关系如下:

  1. 低 0-14 位,共计 15 位为 index 的值
  2. 高 15-30 位,共计 16 位为 sequence number 的值

当 IPCMNI 扩展模式使能时,IPC id 值的生成规则如下:

  1. 低 0-23 位,共计 24 位为 index 的值
  2. 高 24-30 位为 sequence number 的值

Exercises 3.1:获取 ipc_perm 与 seq number 的值

示例代码:

int
main(int argc, char **argv)
{
	int		i, msqid;
	struct msqid_ds info;

	for (i = 0; i < 20; i++) {
		msqid = Msgget(IPC_PRIVATE, SVMSG_MODE | IPC_CREAT);
		printf("msqid = %d\n", msqid);
		Msgctl(msqid, IPC_STAT, &info);
		
		printf("ipc_perm seq number is %d\n", info.msg_perm.__seq);
		Msgctl(msqid, IPC_RMID, NULL);
	}

	exit(0);
}

运行结果如下:

msqid = 921370624
ipc_perm seq number is 28118
msqid = 921370625
............................
ipc_perm seq number is 28119
msqid = 921403393

每 64 个 msqid seq 递增一次。数字上的关系为 seq * 512 * 64 + 1 为下一组 64 个 msgid 的起始值。

10 进制与 2 进制对比:

110110111010110 28118
110110111010110000000000000001 921370625

能够发现 28118 是 921370625 的高 15 位值。

Exercises 3.2:msq 每次获取返回的 id 值的变化特点

测试记录
0~63
32768-32831
65536- 65599
98304-98367

每 64 个 id 值为一组连续空间,超过 64 后起始值按照某种规律重新生成。

Exercises3.3:创建 fifo 与 msgq 时对 umask 的使用

umask 的值:0022
示例代码:

int		i, msqid;

#define TEST_FIFOPATH "/tmp/test_fifo"
	struct msqid_ds info;
	struct stat statbuf;

	mkfifo(TEST_FIFOPATH, 0666);
	stat(TEST_FIFOPATH, &statbuf);
	unlink(TEST_FIFOPATH);
	printf("fifo perm is %o\n", statbuf.st_mode);

	msqid = Msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
	Msgctl(msqid, IPC_STAT, &info);
	Msgctl(msqid, IPC_RMID, NULL);
	printf("msgq perm is %o\n", info.msg_perm.mode);

测试结果:

fifo perm is 10644
msgq perm is 666

system V ipc 消息队列创建时不会使用 umask 来去除必要的权限,fifo 在创建时会使用 umask 去掉必要的权限。

man mkfifo 得到的信息:

DESCRIPTION
       mkfifo()  makes a FIFO special file with name pathname.  mode specifies the FIFO's permissions.  It is modified by the process's umask
       in the usual way: the permissions of the created file are (mode & ~umask).q

man msgget 未搜索到任何与 umask 相关的内容与测试结果一致。

Exercises3.4:服务端为客户端创建唯一消息队列时那种方式更适用?

1. 使用程序名作为固定的路径名作为参数用 ftok 生成 key 来创建

在这种方式下,编码约定、引入三方通信框架将路径名代表的消息队列通知客户端,客户端使用相同的路径名用 ftok 生成 key 获取 server 创建的消息队列。当需要创建多个消息队列时,需要指定多个路径以区分不同的实例。

2. 使用 IPC_PRIVATE 标志让内核自行分配 id 创建

在这种方式下,服务端与客户端之间需要依赖第三方的通信框架以将消息队列的标识符通知客户端,当有多个客户端时,使用这种方式避免了第一种方式中提供多个文件路径的行为,然而此种方式却不能简单的通过编码约定来关联同一个消息队列。

Exercises3.5:使用 find 批量化查找文件并制作参数使用 ftok 生成 key

示例命令:

find / -print   | xargs -i ./svipc/ftok '{}' > output

初步观察未找到相同的 key。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值