System V 共享内存(一)

1. ftok 函数

描述

利用路径名与标识符生成一个供 System V IPC 使用的 key 值

概要

    #include <sys/types.h>
    #include <sys/ipc.h>
    key_t ftok(const char *pathname, int proj_id);

返回值

成功返回 key_t 的值,失败返回 -1

操作示例

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>

int main()
{
  char filename[50];
  struct stat buf;
  int ret;
  strcpy(filename, "/tmp/shm");
  ret = stat(filename, &buf);
  if (ret == -1)
  {
    perror("stat error");
    return -1;
  }
  fprintf(stdout, "ftok(filename, 1024)= %x, st_ino= %x, st_dev=%x\n", ftok(filename, 1024), buf.st_ino, buf.st_dev);
  // 输出:ftok(filename, 1024)= 12996, st_ino= 4032996, st_dev=fd01
  // 本质上 ftok 应该输出值为 0x00012996 , 即1024后两位,st_dev后两位,st_ino后两位
}

2. semctl 函数

描述

System V 信号量控制和操作函数

概要

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>

    int semctl(int semid, int semnum, int cmd, ...);

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) */
    };

返回值

失败时, semctl() 返回 -1 ;成功当cmd = SETALL 时返回 0

3. semop 函数

描述

semop, semtimedop - System V semaphore operations

概要

// 按 sops 结构指定的方式处理semid指向的信号量集中的 nsops 个信号量
int semop(int semid, struct sembuf *sops, size_t nsops);
struct sembuf {
    unsigned short sem_num;  /* semaphore number, the first semaphore of
                                the set is numbered 0 */
    short          sem_op;   /* semaphore operation */
    short          sem_flg;  /* operation flags */
};
// sem_op 为正数时是 V 操作,即释放资源
// sem_op 为负数时是 P 操作,即获取资源
// sem_flg = IPC_NOWAIT or SEM_UNDO

返回值

If successful, semop() return 0; otherwise they return -1 with errno indicating the error.

4. shmat 与 shmdt

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

返回值

On success, shmat() returns the address of the attached shared memory segment; on error, (void *) -1 is returned, and errno is set to indicate the cause of the error.
On success, shmdt() returns 0; on error -1 is returned, and errno is set to indicate the cause of the error.

5. 示例代码

具体使用方法,详见附件 shared_memory_demo.zip , 以下仅是对shm系统调用的封装:

#define MAX_NUM 128
// 共享内存消息结构体
struct shm_data {
  int data[MAX_NUM];
  int datalength;
};
// 用于初始化信号量结构体
union semun {
  int val;
  struct semid_ds *buf;
  unsigned short int *array;
  struct seminfo *__buf;
};
// 创建共享内存 id
int get_shmid() {
  int shmid;
  key_t key;

  if ((key = ftok("/tmp/shm/", 1024)) < 0) {
    perror("ftok error");
    return -1;
  }

  shmid = shmget(key, sizeof(struct shm_data), IPC_CREAT|0777);
  return shmid;
}
// 创建信号量 id
int get_semaphoreid() {
  int semid;
  key_t key;

  if ((key = ftok("/tmp/sem/", 1024)) < 0) {
    perror("ftok error");
    return -1;
  }

  semid = semget(key, 1, IPC_CREAT|0777);
  return semid;
}
// 初始化信号量
int semaphore_init(int semid) {
  union semun argument;
  unsigned short int values[1];
  values[0] = 1;
  argument.array = values;
  return semctl(semid, 0, SETALL, argument);
}
// 对信号量进行 p 操作
int semaphore_p(int semid) {
  struct sembuf operations[1];
  operations[0].sem_num = 0;
  operations[0].sem_op = -1;
  operations[0].sem_flg = SEM_UNDO;
  return semop(semid, operations, 1);
}
// 对信号量进行 v 操作
int semaphore_v(int semid) {
  struct sembuf operations[1];
  operations[0].sem_num = 0;
  operations[0].sem_op = 1;
  operations[0].sem_flg = SEM_UNDO;
  return semop(semid, operations, 1);
}

下一篇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值