前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >进程间通讯(六).semaphore and shared(3)

进程间通讯(六).semaphore and shared(3)

作者头像
franket
发布2021-09-15 20:19:55
6240
发布2021-09-15 20:19:55
举报
文章被收录于专栏:技术杂记
代码语言:javascript
复制
EINVAL:参数size小于SHMMIN或大于SHMMAX

EEXIST:预建立key所指的共享内存,但已经存在

EIDRM:参数key所指的共享内存已经删除

ENOSPC:超过了系统允许建立的共享内存的最大值(SHMALL)

ENOENT:参数key所指的共享内存不存在,而参数shmflg未设IPC_CREAT位

EACCES:没有权限

ENOMEM:核心内存不足

shmat

sys/shm.h 中有关于 shmat 的原型声明

代码语言:javascript
复制
/* Attach shared memory segment.  */
extern void *shmat (int __shmid, __const void *__shmaddr, int __shmflg)
     __THROW;

连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问

__shmid 共享内存标识符

__shmaddr 指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置

__shmflg SHM_RDONLY:为只读模式,其他为读写模式

如果成功则返回附加好的共享内存地址,如果出错,则返回-1,错误原因存于error中

Tip: fork后子进程继承已连接的共享内存地址;exec后该子进程与已连接的共享内存地址自动脱离(detach);进程结束后,已连接的共享内存地址会自动脱离(detach)

有以下几种错误

代码语言:javascript
复制
EACCES:无权限以指定方式连接共享内存

EINVAL:无效的参数shmid或shmaddr

ENOMEM:核心内存不足

semget

sys/sem.h 中有关于 semget 的原型声明

代码语言:javascript
复制
/* Get semaphore.  */
extern int semget (key_t __key, int __nsems, int __semflg) __THROW;

得到一个信号量集标识符或创建一个信号量集对象并返回信号量集标识符

__key 通常要求此值来源于ftok返回的IPC键值

__nsems 创建信号量集中信号量的个数,该参数只在创建信号量集时有效

__semflg IPC_CREAT:当 semflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的信号量集,则新建一个信号量集;如果存在这样的信号量集,返回此信号量集的标识符;IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的信号量集,则新建一个消息队列;如果存在这样的信号量集则报错

如果成功则返回信号量集的标识符,如果失败则返回-1,错误原因存于error中

有以下几种错误

代码语言:javascript
复制
EACCESS:没有权限

EEXIST:信号量集已经存在,无法创建

EIDRM:信号量集已经删除

ENOENT:信号量集不存在,同时semflg没有设置IPC_CREAT标志

ENOMEM:没有足够的内存创建新的信号量集

ENOSPC:超出限制

semop

sys/sem.h 中有关于 semop 的原型声明

代码语言:javascript
复制
/* Operate on semaphore.  */
extern int semop (int __semid, struct sembuf *__sops, size_t __nsops) __THROW;

对信号量集标识符为semid中的一个或多个信号量进行P操作或V操作

__semid 信号量集标识符

__sops sembuf 结构体的指针,这个结构体里存放着操作的内容,结构体相关内容可以参看前面的说明

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

如果成功则返回信号量集的标识,如果出错,则返回-1,错误原因存于error中

有以下几种错误

代码语言:javascript
复制
E2BIG:一次对信号量个数的操作超过了系统限制

EACCESS:权限不够

EAGAIN:使用了IPC_NOWAIT,但操作不能继续进行

EFAULT:sops指向的地址无效

EIDRM:信号量集已经删除

EINTR:当睡眠时接收到其他信号

EINVAL:信号量集不存在,或者semid无效

ENOMEM:使用了SEM_UNDO,但无足够的内存创建所需的数据结构

ERANGE:信号量值超出范围

shmdt

sys/shm.h 中有关于 shmdt 的原型声明

代码语言:javascript
复制
/* Detach shared memory segment.  */
extern int shmdt (__const void *__shmaddr) __THROW;

与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存

__shmaddr 连接的共享内存的起始地址

成功则返回0,出错则返回-1,错误原因存于error中

本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程

有以下几种错误

代码语言:javascript
复制
EINVAL:无效的参数shmaddr

semctl

sys/sem.h 中有关于 semctl 的原型声明

代码语言:javascript
复制
/* Semaphore control operation.  */
extern int semctl (int __semid, int __semnum, int __cmd, ...) __THROW;

在指定的信号集或信号集内的某个信号上执行控制操作

__semid 信号量集标识符

__semnum 信号量集数组上的下标,表示某一个信号量

__cmd 可以取以下的宏

代码语言:javascript
复制
/* Commands for `semctl'.  */
#define GETPID          11              /* get sempid */
#define GETVAL          12              /* get semval */
#define GETALL          13              /* get all semval's */
#define GETNCNT         14              /* get semncnt */
#define GETZCNT         15              /* get semzcnt */
#define SETVAL          16              /* set semval */
#define SETALL          17              /* set all semval's */

sembuf 共用体

bits/sem.h 中有关于 sembuf 的说明

代码语言:javascript
复制
/* The user should define a union like the following to use it for arguments
   for `semctl'.

   union semun
   {
     int val;                           <= value for SETVAL
     struct semid_ds *buf;              <= buffer for IPC_STAT & IPC_SET
     unsigned short int *array;         <= array for GETALL & SETALL
     struct seminfo *__buf;             <= buffer for IPC_INFO
   };

   Previous versions of this file used to define this union but this is
   incorrect.  One can test the macro _SEM_SEMUN_UNDEFINED to see whether
   one must define the union or not.  */

这是一个共用体,用作 semctl 的参数,不同的共用体成员可以用于不同的情景中


semid_ds 结构体

bits/sem.h 中有关于 semid_ds 的说明

代码语言:javascript
复制
/* Data structure describing a set of semaphores.  */
struct semid_ds
{
  struct ipc_perm sem_perm;             /* operation permission struct */
  __time_t sem_otime;                   /* last semop() time */
  unsigned long int __unused1;
  __time_t sem_ctime;                   /* last time changed by semctl() */
  unsigned long int __unused2;
  unsigned long int sem_nsems;          /* number of semaphores in set */
  unsigned long int __unused3;
  unsigned long int __unused4;
};

这个结构体的指针可以在semctl中作为参数获取信号量的信息


seminfo 结构体

bits/sem.h 中有关于 seminfo 结构体的说明

代码语言:javascript
复制
struct  seminfo
{
  int semmap;
  int semmni;
  int semmns;
  int semmnu;
  int semmsl;
  int semopm;
  int semume;
  int semusz;
  int semvmx;
  int semaem;
};

这个结构体的指针可以在semctl中作为参数获取信号量的信息


shmctl

sys/shm.h 中有关于 shmctl 的原型声明

代码语言:javascript
复制
/* Shared memory control operation.  */
extern int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf) __THROW;

完成对共享内存的控制

__shmid 共享内存标识符

__cmd IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中;IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内;IPC_RMID:删除这片共享内存

__buf 共享内存管理结构体指针

如果成功则返回0,如果出错则返回-1,错误原因存于error中

可能的错误有

代码语言:javascript
复制
EACCESS:参数cmd为IPC_STAT,确无权限读取该共享内存

EFAULT:参数buf指向无效的内存地址

EIDRM:标识符为msqid的共享内存已被删除

EINVAL:无效的参数cmd或shmid

EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行

IPC_X 宏定义

bits/ipc.h 中有关 IPC_X 的宏定义

代码语言:javascript
复制
/* Control commands for `msgctl', `semctl', and `shmctl'.  */
#define IPC_RMID        0               /* Remove identifier.  */
#define IPC_SET         1               /* Set `ipc_perm' options.  */
#define IPC_STAT        2               /* Get `ipc_perm' options.  */
#ifdef __USE_GNU
# define IPC_INFO       3               /* See ipcs.  */
#endif

shmid_ds 结构体

bits/shm.h 中有关 shmid_ds 的宏定义

代码语言:javascript
复制
/* Data structure describing a shared memory segment.  */
struct shmid_ds
  {
    struct ipc_perm shm_perm;           /* operation permission struct */
    size_t shm_segsz;                   /* size of segment in bytes */
    __time_t shm_atime;                 /* time of last shmat() */
#if __WORDSIZE == 32
    unsigned long int __unused1;
#endif
    __time_t shm_dtime;                 /* time of last shmdt() */
#if __WORDSIZE == 32
    unsigned long int __unused2;
#endif
    __time_t shm_ctime;                 /* time of last change by shmctl() */
#if __WORDSIZE == 32
    unsigned long int __unused3;
#endif
    __pid_t shm_cpid;                   /* pid of creator */
    __pid_t shm_lpid;                   /* pid of last shmop */
    shmatt_t shm_nattch;                /* number of current attaches */
    unsigned long int __unused4;
    unsigned long int __unused5;
  };

ipc_perm 结构体

bits/ipc.h 中有关 ipc_perm 结构体的宏定义

代码语言:javascript
复制
/* Data structure used to pass permission information to IPC operations.  */
struct ipc_perm
  {
    __key_t __key;                      /* Key.  */
    __uid_t uid;                        /* Owner's user ID.  */
    __gid_t gid;                        /* Owner's group ID.  */
    __uid_t cuid;                       /* Creator's user ID.  */
    __gid_t cgid;                       /* Creator's group ID.  */
    unsigned short int mode;            /* Read/write permission.  */
    unsigned short int __pad1;
    unsigned short int __seq;           /* Sequence number.  */
    unsigned short int __pad2;
    unsigned long int __unused1;
    unsigned long int __unused2;
  };

总结

以下函数可以进行信号量和共享内存的创建与控制

  • shmget
  • shmat
  • shmdt
  • shmctl
  • semget
  • semop
  • semctl

通过各方面资料弄懂其参数的意义和返回值的类型,是熟练掌握的基础

原文地址

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • shmat
  • semget
  • semop
  • shmdt
  • semctl
  • sembuf 共用体
  • semid_ds 结构体
  • seminfo 结构体
  • shmctl
  • IPC_X 宏定义
  • shmid_ds 结构体
  • ipc_perm 结构体
  • 总结
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档