👾
scat's blog
  • introduction
  • TOEFL
  • cs161 su23 mid-term cheat sheet
  • 👀学习和观察优秀先辈
  • 🧐如何使用搜索引擎
  • 😎CS106L note
  • ⚙️操作系统编程作业速查手册
  • 🐈developer_roadmap.scat()
  • 陆本cs论纲
  • 计网笔记合集
  • 软件工程八股
  • ⛏️数据仓库与数据挖掘复习总结
  • 操作系统八股
Powered by GitBook
On this page
  • fork
  • message queue
  • 本部分参考资料
  • msg_queue 里传递的消息格式
  • msgget
  • msgrcv
  • msgsnd
  • 命令行工具
  • ipcs
  • ipcrm -q <queue_id>
  • Linux信号量集
  • 创建新的信号量集或获取已存在的信号量集
  • 对信号量的PV操作
  • 信号量集的控制函数
  • 共享内存
  • shmget
  • shmat
  • shmdt
  • shmctl

操作系统编程作业速查手册

只是一些和作业有关的速记

PreviousCS106L noteNextdeveloper_roadmap.scat()

Last updated 1 year ago

引流:使用linux系统提供的系统调用msgget(),msgrev(),msgctl()编制一个长度为1K的消息发送和接受的程序

fork

fork一个新进程

  • 在父进程中,fork()返回新创建子进程的进程ID

  • 在子进程中,fork()返回0

message queue

POSIX.1‐2017 defination: 3.226 Message Queue 3.226 消息队列 In the context of programmatic message passing, an object to which messages can be added and removed. Messages may be removed in the order in which they were added or in priority order.

在编程消息传递的上下文中,可以向其添加和删除消息的对象。邮件可以按添加顺序或优先级顺序删除。

本部分参考资料

总而言之还是建议看英文原版一手资料手册,中文教程和ai回答的很多细节模糊,会导致debug非常难办

msg_queue 里传递的消息格式

在msg_queue里传递的格式有特定的要求:

  • 结构体里的第一个元素是一个数据类型为long的message type

struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[1];    /* message data */
};

msgget

原型:msgget(key_t key,int flag) 参数含义:

  • key:消息队列的键值。如果该键值对应的消息队列不存在,则根据 flag 参数的值创建一个新的消息队列。

  • flag:控制函数行为的标志,取值可以是 0 或 IPC_CREAT。 返回值:成功后,msgget() 返回消息队列标识符(非负整数) 注意事项:server端flag=0777|IPC_CREAT,0777代表文件权限,含义是表示创建的消息队列的访问权限为所有者、所属组和其他用户都具有读、写和执行权限,IPC_CREAT代表创建队列。而client端flag=0777,无需重复创建新的队列

msgrcv

原型:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg); 参数含义:

  • msgqid:消息队列的标识符。

  • msgp:指向接收消息的缓冲区。

  • msgsz:需要接收消息的大小,注意,不包括mtype

  • msgtyp:指定要接收的消息类型。

    • 如果为 0,则表示接收队列中的第一条消息。

    • 如果不为0,接受mtype==msgtype的消息

  • msgflg:控制函数行为的标志,取值可以是 0 或 IPC_NOWAIT。

  • 函数返回值为成功接收到的消息字节数

msgsnd

原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数含义:

  • msgid:消息队列的标识符。

  • msgp:指向要发送的消息的缓冲区。

  • msgsz:发送消息的长度

  • msgflg:控制函数行为的标志,取值可以是 0 或 IPC_NOWAIT。

  • 函数返回值为 0 表示成功,如果出错则返回 -1

命令行工具

ipcs

在命令行里返回全部的消息队列和状态,示例如下:

juanitahowe@JuanitadeMacBook-Air 消息队列实验 % ipcs
IPC status from <running system> as of Tue Oct 17 11:05:13 CST 2023
T     ID     KEY        MODE       OWNER    GROUP
Message Queues:
q  65536 0x0000004b --rw-rw-rw- juanitahowe    staff

T     ID     KEY        MODE       OWNER    GROUP
Shared Memory:

T     ID     KEY        MODE       OWNER    GROUP
Semaphores:

ipcrm -q <queue_id>

删除某个指定id的消息队列

Linux信号量集

Linux信号量作为IPC机制的一种,与其他通信方式类似,Linux也是通过kern_ipc_perm结构中的key来唯一标志一个信号量集,并通过该结构设置并检查访问权限。针对信号量集,系统维护一个由信号量集组成的数组,数组中的每个单元指向一个信号量集。

创建新的信号量集或获取已存在的信号量集

`int semget(key_t key ,int nsems ,int flag)`

参数说明:

  • key:用户指定一个非0整数型值,对信号量集的打开或存取依赖于semflg参数的取值。

  • nsems:指定打开或者新创建的信号量集将包含的信号量的数目。

  • flag:

    • 若只设置semflg的IPC_CREAT位,则创建一个信号量集,如果该信号量集已经存在,则返回其标识符。

    • semflg的IPC_CREAT|IPC_EXCL位,则创建一个新的信号量集,如果该key值的信号量已经存在,则返回错误信息。

    • 只设置IPC_EXCL而不设置IPC_CREAT位没有任何意义

  • 返回值:正确返回信号量集的标识符,错误时返回-1。

例如,创建一个只包含一个信号量的信号量集:

semid = semget(IPC_PRIVATE,1,IPC_CREAT\|0666);

对信号量的PV操作

`int semop(int semid ,struct sembuf *sops ,unsigned nsops);`

参数说明:

  • semid:是信号量集的标识符,由semget()得到

  • sops:指向一个sembuf结构数组,该数组的每一个元素对以一次信号量操作。

    • struct sembuf解释见下

  • nsops:进行操作信号量的个数,即sops结构变量的个数,需大于或等于1。最常见设置此值等于1,只完成对一个信号量的操作

struct sembuf
{
unsigned short sem_num; /*semaphore index in array*/
short sem_op; /*semaphore operation*/
short sem_flg; /*operation flags*/
};
  • sem_num标明它是信号量集的第几个元素,从0开始

  • sem_op指定信号量采取的操作

    • <0相当于P操作,占有资源

    • >0相当于V操作,释放资源

    • =0进程睡眠直到信号量的值为0

  • sem_flg指明操作的执行模式,两个标志位。一个是IPC_NOWAIT,指明以非阻塞方式操作信号量。一个是SEM_UNDO,指明内核为信号量操作保留恢复值。

当操作信号量(semop)时,sem_flg可以设置SEM_UNDO标识;SEM_UNDO用于将修改的信号量值在进程正常退出(调用exit退出或main执行完)或异常退出(如段异常、除0异常、收到KILL信号等)时归还给信号量。

如信号量初始值是20,进程以SEM_UNDO方式操作信号量减2,减5,加1;在进程未退出时,信号量变成20-2-5+1=14;在进程退出时,将修改的值归还给信号量,信号量变成14+2+5-1=20。

返回值:正确返回0,错误时返回-1

信号量集的控制函数

union semun
{
int val;                    /*value for setval*/
struct semid_ds *buf;        /*buffer for IPC_STAT & IPC_SET*/
unsigned short *array;      /*array for GETALL & SETALL*/
struct seminfo *_buf;       /*buffer for IPC_INFO*/
};

int semctl(int semid ,int semnum ,int cmd ,union semun arg);

参数说明:

  • semid:是信号量集的标识符,由semget()得到

  • semnum:指定semid信号量集的第几个信号量,在撤销信号量集时,此参数可缺省。

  • cmd:指定操作类型。

  • arg:数据类型是共同体类型semun,该类型在include/linux/sem.h中定义

    取值 含义

    GETVAL 返回semnum指定的信号量的semval域值

    SETVAL 指定semval域值为arg.val

    GETPID 返回semnum指定信号量sempid

    GETNCNT 返回semncnt

    GETZCNT 返回semzcnt

    GETALL 返回所有信号量的值,结果保存到arg.array中

    SETALL 通过arg.array更新所有信号量的值

    IPC_STAT 获取信号量集的arg.array,存入arg.buf

    IPC_SET 将arg.buf数据结构的sem_perm.uid,sem_perm.gid,sem_perm.mode赋给sem_array,此操作仅限root、sem_perm.cuid或sem_perm.uid

    IPC_RMID 删除指定信号量集。此操作仅限root、sem_perm.cuid或sem_perm.uid

    IPC_INFO 获取信号量集的相关信息存放于arg.buf中

返回值:正确时根据cmd的的不同返回值或0,错误时返回-1。

例如:撤销信号量集 semctl(semid ,IPC_RMID ,0)

共享内存

shmget

原型和头文件:

#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

参数分别是:

  • 进程间通信键值

  • 共享内存大小

  • 权限等级

shmat

shmat 函数是 Linux 系统编程中用于将共享内存连接到当前进程的地址空间中的函数


void *shmat(int shmid, const void *shmaddr, int shmflg);

该函数的参数包括共享内存标识符、连接地址和标志等。调用该函数会返回一个指向共享内存第一个字节的指针。

  • 共享内存标识符:由 shmget 函数返回的共享内存标识符。

  • 连接地址:指定共享内存连接到当前进程的地址,通常设置为 NULL。

  • 标志:指定连接方式,包括只读和读写等。

shmdt

shmdt 函数是 Linux 系统编程中用于将共享内存从当前进程的地址空间中分离的函数之一。它的原型如下:


int shmdt(const void *shmaddr);

该函数的参数是由 shmat 函数返回的地址指针。调用该函数会将共享内存从当前进程的地址空间中分离,但并不会删除共享内存。调用成功时返回 0,失败时返回 -1。

shmctl

shmctl 函数是 Linux 系统编程中用于控制共享内存的函数之一。它的原型如下:

#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

该函数的参数包括共享内存标识符、命令和 shmid_ds 结构体等。调用该函数可以对共享内存进行多种操作,包括获取共享内存信息、设置共享内存信息、删除共享内存等。

  • shmid:由 shmget 函数返回的共享内存标识符。

  • cmd:指定需要执行的操作,包括获取共享内存信息、设置共享内存信息、删除共享内存等。

  • shmid_ds 结构体:用于传递共享内存信息,包括共享内存的大小、访问权限、最后一次连接时间等。

实际接收消息的缓冲区,建议为一个数组或者结构体较为便利,具体细节参考

⚙️
某手册网站
man7
这个回答