Unix环境进程间通信(二)

原创 2006年06月01日 22:58:00

1.1        共享内存

1.1.1   数据结构

struct shmid_ds {
struct ipc_perm  shm_perm;    /* 超作许可权数据结构指针 */

    int              shm_segsz;   /* 共享存储段大小 (bytes) */

    time_t          shm_atime;   /* 最后调用shmat时间 */

    time_t          shm_dtime;   /* 最后调用shmdt的时间 */

    time_t          shm_ctime;   /* 最后调用shmctl的改变的时间 */

    unsigned short   shm_cpid;    /*创建者的进程ID */

    unsigned short   shm_lpid;    /* 最后对共享存储段进行操作的进程ID */

short           shm_nattch;  /* 当前连接数 */
};

struct ipc_perm {

     key_t  key;
     ushort uid;   /* owner euid and egid */
     ushort gid;
     ushort cuid;  /* creator euid and egid */
     ushort cgid;
     ushort mode;  /* lower 9 bits of shmflg */
     ushort seq;   /* sequence number */
};

 

1.1.2   API

4.4 #include <sys/ipc.h>

#include <sys/shm.h>

打开创建存储段

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

返回:失败-1, 成功返回非负的共享存储段id

 

第一个参数key是共享存储关键字。它有特殊值IPC_PRIVATE表示总是创建一个进程私有的共享存储段。

key值不等于IPC_PRIVATE时,shmget动作取决于最后一个参数shmflg标志:

1. IPC_CREAT 单独设置此标志,当系统中不存在相同key时,创建一个新的共享存储段,否则返回已存在的共享存储段。

2. IPC_EXCL 单独设置不起作用。与 IPC_CREAT同时设置时,当系统中存在相同key时,错误返回。保证不会打开一个已存在的共享存储段。

如果没有指定IPC_CREATE并且系统中不存在相同key值的共享存储段,将失败返回。

第三个参数也可以设置共享存储段的访问权限,用或于上面的值操作。

第二个参数size指明要求的共享存储段的大小。当key指定的共享存储段已存在时,取值范围为0和已存在共享段大小。或简单指定为0

成功后此函数返回共享存储段id,同时创建于参数key相连的数据结构shmid_ds。此节构为系统内部使用。

 

4.4 #include <sys/ipc.h>

#include <sys/shm.h>

存储段控制函数。可获得shmid_ds全部内容

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

返回:失败-1并置errno, 成功返回0

第一个参数,必须由shmget返回的存储段的idcmd为指定要求的操作。

CMD

说明

参数

IPC_STAT

放置与shmid相连的shmid_ds结构当前值于buf所指定用户区

buf

IPC_SET

buf指定的结构值代替与shmid相连的shmid_ds结构值

buf

IPC_RMID

删除制定的信号量集合

 

SHM_LOCK

锁住共享存储段。只能由超级管理员使用

 

SHM_UNLOCK

unlock共享存储段。只能由超级管理员使用

 

 

//创建/打开共享存储段,连接他到用户地址空间,返回他在用户空间的地址

void* shminit(key_t key, char* mode_str, int target=1) {

       int shmid;

       int mode;

       void* retval;

       if (mode_str == NULL) {

              mode = 0660;

       } else {

              sscanf(mode_str, "%o", &mode);

       }

       if (target == 0 ) {

              if ((shmid = shmget(key, sizeof(exchange_T), mode | IPC_CREAT)) == -1)

                     perror("cannot create shm--");

       } else if (target == 1) {

              if ((shmid = shmget(key, sizeof(exchange_T), mode)) == -1)

                     perror("cannot get shm--");

       }

       if ((retval = shmat(shmid, (void *)0, 0)) == (void*)-1)

              perror("shmmat");

       return retval;

}

 

int rm_shm(key_t key) {

       int status, shmid;

      

       if ((shmid = shmget(key, sizeof(exchange_T), 0x660 | IPC_CREAT)) < 0)

                     perror("cannot get shm");

       if ((status = shmctl(shmid, IPC_RMID, NULL)) < 0)

              perror("shmctl IPC_RMID");

       return status;

}

 

4.5 #include <sys/types.h>

   #include <sys/shm.h>

存储段连接

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

返回:失败-1并置errno, 成功返回连接的实际地址

第一个参数,必须由shmget返回的存储段的id

第二个参数指明共享存储段要连接到的地址。0,系统为我们创建一个适当的地址值。否则自己指定

第三个参数shmflg可以设成:SHM_RND, SHM_RDONLYSHM_RND为自己指定连接地址时用。SHM_RDONLY说明此存储段只读。

 

4.6 #include <sys/types.h>

   #include <sys/shm.h>

存储段分离

int shmdt(const void * shmaddr);

返回:失败-1并置errno, 成功返回0

分离由shmaddr指定的存储段。此值应该由shmat返回的值。

此函数不是删除共享存储段,而是从当前进程分离存储段。

当进程推出时,系统会自动分离它连接的所有共享段。

1.1.3   Example

client.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <errno.h>

#define SHMSZ 27
int main(void) {
       exchange_T* shm;
       int producer, consumer, i;
       key_t key1 = 123, key2 = 456;

       consumer = open_semaphore_set(key1, 1);
       procuder = open_semaphore_set(key2, 1);

       shm = (exchange_T*)shminit(ftock("shared", 0));

       for (i = 0; ; i++) {
              semaphore_V(consumer);
              semaphore_P(producer);

              printf("Data recieived:%s, sequence:%d/n", shm->buf, shm->seg);

              if (strncmp(shm->buf, "end", 3) == 0)
                     break;
       }

       rm_semaphore(producer);
       rm_semaphore(consumer);

       exit(0);
}

 

server.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <errno.h>
#include "outshm.h"

#define SHMSZ 27

int main(void) {

       exchage_T *shm, *s;
       int producer, consumer, i;
       char readbuf[BUFSIZE];
       key_t key1 = 123, key2 = 456;

       consumer = open_semaphore_set(key1, 1);
       init_a_semaphore(consumer, 0, 0);

       producer = open_semaphore_set(key2, 1);
       init_a_semaphore(producer, 0, 0);

       shm = (exchange_T*)shminit(ftok("shared", 0));

       for(i = 0; ; i++) {
              printf("Enter some text:");
              fgets(readbuf, BUFSIZE, stdin);
              semaphore_P(consumer);
              shm->seq = i;
              sprintf(shm->buf, "%s", readbuf);
              semaphore_V(producer);
              if(strncmp(readbuf, "end", 3) == 0)
                     break;
       }

       exit(0);
}

 

相关文章推荐

UNIX环境高级编程-第15章- 进程间通信 - 二

15.6 XSI IPC 有三种IPC我们称作XSI IPC,即消息队列,信号量和共享存储器,他们之间有很多相似之处。 15.6.1 标识符和键 每个内核中的IPC结构(消息队列,信号量或共享存...

《UNIX环境高级编程》第17章 高级进程间通信

17.1 引言前面两章讨论了UNIX系统提供的各种IPC,其中包括管道和套接字。 本章介绍一个高级IPC-UNIX域套接字,并说明它的使用方法。 这种形式的IPC可以在同一计算机上运行的两个进程之...

UNIX环境高级编程(第15章 进程间通信)

进程间通信的方式包括管道、消息队列、信号量和共享存储。通过这些机制,同一台计算机上运行的进程可以互相通信。...

《UNIX环境高级编程》第15章 进程间通信

15.1 引言第8章说明的进程控制原语,并且观察了如何调用多个进程。但是这些进程间交互信息的唯一途径就是传送打开的文件,可以经由fork或exec来传送,也可以通过文件系统来传送。 本章讨论经典IP...

Unix环境进程间通信

  新一篇: Unix环境进程间通信(二)1.1        信号量SystemV的信号量使用方法1.1.1   数据结构#include #include #include 1.struct se...
  • haisi05
  • haisi05
  • 2011年06月22日 00:05
  • 174

《UNIX环境高级编程》十五进程间通信读书笔记

1、管道 管道的局限性: (1)历史上,它们是半双工的(即数据只能在一个方向上流动)。 (2)管道只能在具有公共祖先的两个进程之间使用。 半双工管道是最常用的IPC形式。每当在管道中键入一个命...

UNIX环境高级编程笔记——高级IO,进程间通信,套接字,高级进程间通信

14 高级IO非阻塞IO:这里我要抽时间看看AIO的使用。记录锁:运行一个进程修改一个文件的一部分的时候,禁止其进程修改统一区域。流在用户经常和设备驱动程序间提供了一个全双工通道。readv和writ...

UNIX网络编程 卷二 进程间通信

  • 2010年04月03日 09:33
  • 14.77MB
  • 下载

《unix高级环境编程》进程间通信——信号量

这里所介绍的信号量是一种
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Unix环境进程间通信(二)
举报原因:
原因补充:

(最多只允许输入30个字)