福建宏盛建设集团有限公司网站,做视频网站要什么软件下载,网站建设两个方面,呼市网站设计公司文章目录 一、共享内存1.1 一些接口1. shmget 函数#xff1a;申请一个 system v 的共享内存块2. ftok 函数#xff1a;设置唯一标识码3. shmctl 函数#xff1a;控制 system v 的共享内存块#xff08;可以删除、查看...#xff09;4. shmat 函数#xff1a;将进程与共享… 文章目录 一、共享内存1.1 一些接口1. shmget 函数申请一个 system v 的共享内存块2. ftok 函数设置唯一标识码3. shmctl 函数控制 system v 的共享内存块可以删除、查看...4. shmat 函数将进程与共享内存块 关联\ 挂接attach5. shmdt 函数将进程与共享内存块 去关联detach 1.2 一些命令1. ipcs - - 查看三种 ipc 资源2. ipcrm -- 删除某种 ipc 资源 1.3 结论 二、消息队列1. msgget 函数创建消息队列2. msgctl 函数3. msgsnd 和 msgrcv 函数发送和接收消息 三、信号量1. semget2. semctl 函数可以获取信号量的相关属性3. semop 函数对信号量进行操作 总结 一、共享内存
我们知道进程间通信的本质就是让不同的进程看到同一份资源
这里要介绍的同一份资源就是内存块即 共享内存shared memory简写为 shm 共享内存的原理 1.创建key 和 共享内存 2.关联进程 和 取消关联 3.释放共享内存 内存中的每块共享内存会有一个 struct shm 结构体里面放着共享内存的全部属性OS 通过这个结构体建立链表关系来对所有的共享内存进行管理就等于把管理 shm 的问题转化成了管理链表的问题。
故 共享内存 共享内存的内核数据结构 伪代码struct shm 真正开辟的内存空间 1.1 一些接口
1. shmget 函数申请一个 system v 的共享内存块
头文件
#include sys/ipc.h
#include sys/shm.h// umask的头文件如下
#include sys/types.h
#include sys/stat.hint shmget(key_t key, size_t size, int shmflg); 参数 key 使用 ftok 函数设置的唯一标识码他虽由用户设置却是在内核中使用的 参数 size 需要申请共享内存块的大小单位为字节不足 PAGE 页4KB时会向上对齐到 PAGE 页 参数 shmflg 选项 IPC_CREAT and IPC_EXCL 单独使用 IPC_CREAT创建一个共享内存如果共享内存不存在就创建如果已经存在就获取已经存在的共享内存并返回。 IPC_CREAT | IPC_EXCL IPC_EXCL 必须要配合 IPC_CREAT 使用创建一个共享内存如果共享内存不存在就创建如果已经存在就出错返回 意味着一起使用时如果创建成功对应的shm一定是最新的 IPC_CREAT | IPC_EXCL | 0666 上面的基础上添加权限可以配合函数 umask(0) 使用 返回值 成功会返回一个共享内存标识符失败返回 -1 2. ftok 函数设置唯一标识码
头文件
#include sys/types.h
#include sys/ipc.hkey_t ftok(const char *pathname, int proj_id); 参数 pathname 用户设置的路径 参数 proj_id 用户设置的项目 id 返回值 根据用户传入的参数结合一定的算法返回一个冲突概率很低的值。ket_t 就是一个 32 位的整数是对 int 的封装 3. shmctl 函数控制 system v 的共享内存块可以删除、查看…
头文件
#include sys/ipc.h
#include sys/shm.h int shmctl(int shmid, int cmd, struct shmid_ds *buf); 参数 shmid 需要的共享内存块的 shmid 参数 cmd 选项 IPC_STAT把用户传入 shmid 的相应内核数据结构信息复制到 buf 中在调用者有读权限的情况下才能成功选项 IPC_RMID删除 shmid 为传入值的共享内存块 输出型参数 buf 需要得到 ipc 信息时传一个相应类型的值用来接收结果 返回值 失败返回 -1成功则根据 cmd 传入的选项返回对应的值 //The buf argument is a pointer to a shmid_ds structure, defined in sys/shm.h as follows:struct shmid_ds {struct ipc_perm shm_perm; /* Ownership and permissions */size_t shm_segsz; /* Size of segment (bytes) */time_t shm_atime; /* Last attach time */time_t shm_dtime; /* Last detach time */time_t shm_ctime; /* Last change time */pid_t shm_cpid; /* PID of creator */pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */shmatt_t shm_nattch; /* No. of current attaches */...};//The ipc_perm structure is defined as follows (the highlighted fields are settable using IPC_SET):struct ipc_perm {key_t __key; /* Key supplied to shmget(2) */uid_t uid; /* Effective UID of owner */gid_t gid; /* Effective GID of owner */uid_t cuid; /* Effective UID of creator */gid_t cgid; /* Effective GID of creator */unsigned short mode; /* Permissions SHM_DEST andSHM_LOCKED flags */unsigned short __seq; /* Sequence number */};
4. shmat 函数将进程与共享内存块 关联\ 挂接attach
头文件
#include sys/types.h
#include sys/shm.hvoid *shmat(int shmid, const void *shmaddr, int shmflg); 参数 shmid 需要的共享内存块的 shmid 参数 shmaddr 用户可以选择虚拟地址作为共享内存块的起始地址用户一般不定义设为 nullptr 让 OS 自主定义即可 参数 shmflg 选项 SHM_RDONLY只读0可以读写 返回值 挂接成功返回共享内存块的虚拟地址的起始地址 5. shmdt 函数将进程与共享内存块 去关联detach
头文件
#include sys/types.h
#include sys/shm.hint shmdt(const void *shmaddr); 参数 shmaddr 共享内存块的起始地址 返回值 去关联成功返回 0失败返回 -1 1.2 一些命令
1. ipcs - - 查看三种 ipc 资源
ipcs 就是进程间通信ipc资源
ipcs可以查看 消息队列、共享内存亏块、信号量 -m查看 共享内存块memory -s查看 信号量semaphore
perms权限
nattach当前 ipc 挂接的进程数2. ipcrm – 删除某种 ipc 资源
ipcrm删除一个 消息队列、共享内存亏块、信号量 -m删除一个共享内存块后接 shmid
1.3 结论 两个进程管道通信一次需要进行两次复制。而共享内存间的通信可以让进程们直接在自己映射的地址空间中访问减少了拷贝次数 管道单方面关闭读写端会有相应的保护而共享内存没有保护机制同步互斥。管道通过系统接口通信共享内存直接通信 互斥任何一个时刻都只允许一个执行流在进行共享资源的访问叫做加锁 我们把任何一个时刻都只允许一个执行流在进行访问的共享资源叫做 临界资源。凡是访问临界资源的代码叫做临界区控制进出临界区的手段造就了临界资源。 二、消息队列
1. msgget 函数创建消息队列
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/msg.hint msgget(key_t key, int msgflg) 参数 key 使用 ftok 函数设置的唯一标识码 参数 msgflg 选项 IPC_CREAT and IPC_EXCL 单独使用 IPC_CREAT创建一个共享内存如果共享内存不存在就创建如果已经存在就获取已经存在的共享内存并返回。 IPC_CREAT | IPC_EXCL IPC_EXCL 必须要配合 IPC_CREAT 使用创建一个共享内存如果共享内存不存在就创建如果已经存在就出错返回 意味着一起使用时如果创建成功对应的shm一定是最新的 IPC_CREAT | IPC_EXCL | 0666 上面的基础上添加权限可以配合函数 umask(0) 使用 返回值 成功则返回消息队列的标识符 2. msgctl 函数
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/msg.hint msgctl(int msqid, int cmd, struct msqid_ds *buf); 参数 msqid 需要的消息队列的 msqid 参数 cmd 选项 IPC_STAT把用户传入 msqid 的相应内核数据结构信息复制到 buf 中在调用者有读权限的情况下才能成功选项 IPC_RMID删除 msqid 为传入值的共享内存块 输出型参数 buf 需要得到 ipc 信息时传一个相应类型的值用来接收结果 返回值 成功返回 0 的值失败返回 -1 The msqid_ds data structure is defined in sys/msg.h as follows:struct msqid_ds {struct ipc_perm msg_perm; /* Ownership and permissions */time_t msg_stime; /* Time of last msgsnd(2) */time_t msg_rtime; /* Time of last msgrcv(2) */time_t msg_ctime; /* Time of last change */unsigned long __msg_cbytes; /* Current number of bytes inqueue (nonstandard) */msgqnum_t msg_qnum; /* Current number of messagesin queue */msglen_t msg_qbytes; /* Maximum number of bytesallowed in queue */pid_t msg_lspid; /* PID of last msgsnd(2) */pid_t msg_lrpid; /* PID of last msgrcv(2) */};The ipc_perm structure is defined as follows (the highlighted fields are settable using
IPC_SET):struct ipc_perm {key_t __key; /* Key supplied to msgget(2) */uid_t uid; /* Effective UID of owner */gid_t gid; /* Effective GID of owner */uid_t cuid; /* Effective UID of creator */gid_t cgid; /* Effective GID of creator */unsigned short mode; /* Permissions */unsigned short __seq; /* Sequence number */};3. msgsnd 和 msgrcv 函数发送和接收消息
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/msg.hint msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); 参数 msqid 发送和接收访问的同一个消息队列 参数 msgp 发送或接收的数据块 参数 msgsz 发送或接收数据块的大小 参数 msgflg 选项一般填 0 即可 参数 msgtyp msgbuf 里面的 mtype // The msgp argument is a pointer to caller-defined structure of the following general form:struct msgbuf {long mtype; /* message type, must be 0 */char mtext[1]; /* message data */
};三、信号量
信号量 / 信号灯semaphore本质 就是一个计数器是一个描述资源数量的计数器。
举个例子 比如我们任何一个执行流像访问临界资源中的一个子资源的时候不能直接访问需要 先申请信号量资源P操作此时 count-- 。只要申请信号量成功未来就一定能拿到一个子资源。类似摇号 然后进入进程自己的临界区访问对应的临界资源。 使用完成后进程释放信号量资源V操作只要将计数器增加 count就表示将我们对应的资源进行了归还。
至此进程通过执行代码来申请意味着所有进程都得先看到信号量信号量就是一个共享资源。信号量保护共享资源自己却又是一个共享资源
故信号量必须保证自己的 - - 是原子的 也信号量被归类到了进程间通信
信号量部分未完待续~
1. semget
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/sem.hint semget(key_t key, int nsems, int semflg); 参数 key 使用 ftok 函数设置的唯一标识码他虽由用户设置却是在内核中使用的 参数 nsems 申请信号量的个数叫做信号量集 参数 semflg 选项 IPC_CREAT and IPC_EXCL 单独使用 IPC_CREAT创建一个共享内存如果共享内存不存在就创建如果已经存在就获取已经存在的共享内存并返回。 IPC_CREAT | IPC_EXCL IPC_EXCL 必须要配合 IPC_CREAT 使用创建一个共享内存如果共享内存不存在就创建如果已经存在就出错返回 意味着一起使用时如果创建成功对应的shm一定是最新的 IPC_CREAT | IPC_EXCL | 0666 上面的基础上添加权限可以配合函数 umask(0) 使用 返回值 成功会返回一个信号量计数器标识符失败返回 -1 2. semctl 函数可以获取信号量的相关属性
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/sem.hint semctl(int semid, int semnum, int cmd, ...); 参数 semid 需要的信号量的semid 参数 semnum 信号量编号 参数 cmd 选项 IPC_STAT把用户传入 msqid 的相应内核数据结构信息复制到 buf 中在调用者有读权限的情况下才能成功选项 IPC_RMID删除 msqid 为传入值的共享内存块 返回值 成功返回 0 的值失败返回 -1 //This function has three or four arguments, depending on cmd. When there are four, the
//fourth has the type union semun. The calling program must define this union as follows: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(Linux-specific) */};//The semid_ds data structure is defined in sys/sem.h as follows:struct semid_ds {struct ipc_perm sem_perm; /* Ownership and permissions */time_t sem_otime; /* Last semop time */time_t sem_ctime; /* Last change time */unsigned long sem_nsems; /* No. of semaphores in set */};//The ipc_perm structure is defined as follows (the highlighted fields are settable usingIPC_SET):struct ipc_perm {key_t __key; /* Key supplied to semget(2) */uid_t uid; /* Effective UID of owner */gid_t gid; /* Effective GID of owner */uid_t cuid; /* Effective UID of creator */gid_t cgid; /* Effective GID of creator */unsigned short mode; /* Permissions */unsigned short __seq; /* Sequence number */};3. semop 函数对信号量进行操作
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/sem.hint semop(int semid, struct sembuf *sops, unsigned nsops); 参数 sops 需要用户自己定义后传入设置结构体内容以此达到对信号量的 PV 操作等等 //Each semaphore in a System V semaphore set has the following associated values:unsigned short semval; /* semaphore value */unsigned short semzcnt; /* # waiting for zero */unsigned short semncnt; /* # waiting for increase */pid_t sempid; /* ID of process that did last op *///semop() performs operations on selected semaphores in the set indicated by semid.
//Each of the nsops elements in the array pointed to by sops specifies an operation to be performed on a single semaphore.
//The elements of this structure are of type struct sembuf, containing the following members:unsigned short sem_num; /* semaphore number */short sem_op; /* semaphore operation */short sem_flg; /* operation flags */ 总结
共享内存、消息队列、信号量 这三种 ipc 都有各自的内核数据结构体而结构体的第一个成员都是 struct ipc_perm xx_perm。
可以理解为 OS 将这三种 ipc 都放进了一个 struct ipc_perm* ipc_id_arr[] 指针数组中进行管理这里只是做理解解释实际上更复杂。
OS 通过指针可以找到每个结构体同时也是每个结构的第一个成员即 struct ipc_perm xx_perm在其中找到 key 值就可以确定。
要访问里面的内容时以共享内存举例
((struct shmid_ds*)ipc_id_arr[n])-other...对指针进行强转就可以访问到其中内容了这也是一种多态。