Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1142749
  • 博文数量: 148
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1980
  • 用 户 组: 普通用户
  • 注册时间: 2016-12-21 22:26
个人简介

90后空巢老码农

文章分类

全部博文(148)

文章存档

2020年(46)

2019年(54)

2018年(47)

2017年(1)

我的朋友

分类: LINUX

2020-10-07 11:02:54

今天来聊聊用户态System V ipc,也就是常说的信号量、消息队列以及共享内存,以信号量为例

内核当中信号量的数据结构,跟命名空间是相关的,给定的进程属于task_struct->nsproxy->ipc_ns指向的命名空间,ipc_namespace结构如下:

点击(此处)折叠或打开

  1. struct ipc_namespace {
  2.     refcount_t    count;
  3.     struct ipc_ids    ids[3];
  4. ...
  5. };
其中,数组ids当中的每个ipc_ids分别代表当前ipc命名空间下的三种ipc机制0-信号量,1-消息队列,2-共享内存

点击(此处)折叠或打开

  1. struct ipc_ids {
  2.     int in_use;
  3.     unsigned short seq;
  4.     struct rw_semaphore rwsem;
  5.     struct idr ipcs_idr;
  6.     int max_idx;
  7.     int last_idx;    /* For wrap around detection */
  8. #ifdef CONFIG_CHECKPOINT_RESTORE
  9.     int next_id;
  10. #endif
  11.     struct rhashtable key_ht;
  12. };
其中,ipcs_idr是将当前类型的ipc的id映射到对应的内核数据结构kern_ipc_perm的基数树,

点击(此处)折叠或打开

  1. struct kern_ipc_perm {
  2.     spinlock_t    lock;
  3.     bool        deleted;
  4.     int        id;
  5.     key_t        key;
  6.     kuid_t        uid;
  7.     kgid_t        gid;
  8.     kuid_t        cuid;
  9.     kgid_t        cgid;
  10.     umode_t        mode;
  11.     unsigned long    seq;
  12.     void        *security;

  13.     struct rhash_head khtnode;

  14.     struct rcu_head rcu;
  15.     refcount_t refcount;
  16. };
三种ipc在内核当中的表示的第一个元素,都是kern_ipc_perm,当通过基数树找到对应的kern_ipc_perm的指针时候,直接强转就ok了。比如信号量:

点击(此处)折叠或打开

  1. struct sem_array {
  2.     struct kern_ipc_perm    sem_perm;    /* permissions .. see ipc.h */
  3.     time64_t        sem_ctime;    /* create/last semctl() time */
  4.     struct list_head    pending_alter;    /* pending operations */
  5.                         /* that alter the array */
  6.     struct list_head    pending_const;    /* pending complex operations */
  7.                         /* that do not alter semvals */
  8.     struct list_head    list_id;    /* undo requests on this array */
  9.     int            sem_nsems;    /* no. of semaphores in array */
  10.     int            complex_count;    /* pending complex operations */
  11.     unsigned int        use_global_lock;/* >0: global lock required */

  12.     struct sem        sems[];
  13. };
sem_nsems表示当前信号量集合包含信号量的数目,以及在当前信号量上挂着的队列

点击(此处)折叠或打开

  1. struct sem_queue {
  2.     struct list_head    list;     /* queue of pending operations */
  3.     struct task_struct    *sleeper; /* this process */
  4.     struct sem_undo        *undo;     /* undo structure */
  5.     struct pid        *pid;     /* process id of requesting process */
  6.     int            status;     /* completion status of operation */
  7.     struct sembuf        *sops;     /* array of pending operations */
  8.     struct sembuf        *blocking; /* the operation that blocked */
  9.     int            nsops;     /* number of operations */
  10.     bool            alter;     /* does *sops alter the array? */
  11.     bool dupsop;     /* sops on more than one sem_num */
  12. };
如果内核配置了CONFIG_DETECT_HUNG_TASK,task_struct里面才会有ipc相关成员

点击(此处)折叠或打开

  1. struct task_struct{
  2. ...
  3. #ifdef CONFIG_SYSVIPC
  4.     struct sysv_sem            sysvsem;
  5.     struct sysv_shm            sysvshm;
  6. #endif
  7. ...
  8. };
其中,这俩都是用于当前程序崩溃时,释放相关资源的链表

点击(此处)折叠或打开

  1. struct sysv_sem {
  2.     struct sem_undo_list *undo_list;
  3. };

阅读(45) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~