linux IPC共享内存

共享内存相关函数

获得一个共享存储标识符

#include <sys/ipc.h>
#include <sys/shm.h

int shmget(key_t key, size_t size, int shmflg);
返回值:成功共享存储ID,失败-1
key:函数ftok返回值或IPC_PRIVATE(适合用在有亲缘关系的进程中)

size: 共享存储段的长度,以字节为单位
shmflg:权限标志位

共享存储段执行多种操作

#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
返回值:成功0错误-1
shmid:共享内存标识符
cmd:  IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
    IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode赋值到共享内存的shmid_ds结构中
    IPC_RMID:删除这些共享内存
buf:共享内存管理结构体

 shmid_ds结构:

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 */
               ...
           };
struct shmid_ds

一旦创建了一个共享存储段,进程就可调用shmat将其连接到它的地址空间中

#include <sys/types.h>
#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);
返回值:成功共享存储段的指针,失败-1
shmid:共享内存标识符
shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核决定
shmflg:如果指定了SHM_RDONLY位,则以只读方式连接此段,否则以读写的方式连接此段。通常为0

当对共享存储段的操作已经结束时,则调用shmdt与该段分离

#include <sys/types.h>
#include <sys/shm.h>

int shmdt(const void *shmaddr);
返回值:成功0,失败-1
shmaddr:shmat返回的值

程序例程,父子进程间通讯:

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/shm.h>
 4 #include <sys/ipc.h>
 5 #include <string.h>
 6 
 7 #define SIZE 1024
 8 
 9 int main()
10 {
11     int shmid;
12     pid_t pid;
13     char *shmaddr;
14     int flag;
15     struct shmid_ds buf;
16 
17     shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT|0600);
18     if(shmid < 0)
19     {
20         perror("get shm ipc_id error");
21         return -1;
22     }
23 
24     if((pid = fork()) < 0) {
25         perror("get fork error");
26         return -1;
27     } else if(pid == 0) {       /* child */
28         shmaddr = (char *)shmat(shmid, NULL, 0);
29         if((int)shmaddr == -1)
30         {
31             perror("shmat error");
32             return -1;
33         }
34         strcpy(shmaddr, "Hi,I am child process!
");
35         shmdt(shmaddr);
36         return 0;
37     } else {                    /* parent */
38         sleep(3);
39         flag = shmctl(shmid, IPC_STAT, &buf);
40         if(flag == -1)
41         {
42             perror("shmctl error");
43             return -1;
44         }
45 
46         printf("shm_segsz=%d bytes
", buf.shm_segsz);
47         printf("parent pid=%d,shm_cpid=%d 
", getpid(), buf.shm_cpid);
48         printf("child pid=%d,shm_lpid=%d
", pid, buf.shm_lpid);
49         shmaddr = (char *)shmat(shmid, NULL, 0);
50         if((int)shmaddr == -1)
51         {
52             perror("parent:shmat error");
53             return -1;
54         }
55         printf("shmaddr in %s
", shmaddr);
56         shmdt(shmaddr);
57         shmctl(shmid, IPC_RMID, NULL);
58     }
59 
60     return 0;
61 }

进程之间使用共享内存通讯:

shmwrite.c

 1 #include <stdio.h>
 2 #include <sys/ipc.h>
 3 #include <sys/shm.h>
 4 #include <string.h>
 5 
 6 typedef struct {
 7         char name[8];
 8         int age;
 9 }people;
10 
11 int main()
12 {
13         int shmid;
14         key_t key;
15         char temp[8];
16         char pathname[30];
17         people *p_map;
18         int i;
19 
20         strcpy(pathname, "/tmp");
21         key = ftok(pathname, 0x03);
22         if(key == -1)
23         {
24                 perror("ftok error
");
25                 return -1;
26         }
27 
28         printf("key=%d
", key);
29         shmid = shmget(key, 4096,IPC_CREAT|IPC_EXCL|0600);
30         if(shmid == -1)
31         {
32                 perror("shmget error
");
33                 return -1;
34         }
35         printf("shmid=%d
",shmid);
36 
37         p_map = (people *)shmat(shmid, NULL, 0);
38         if((int)p_map == -1)
39         {
40                 perror("shmat error
");
41                 return -1;
42         }
43         memset(temp, 0x00, sizeof(temp));
44         strcpy(temp, "test");
45         temp[4] = '0';
46 
47         for(i=0;i<3;i++)
48         {
49                 temp[4]+=1;
50                 strncpy((p_map+i)->name, temp, 5);
51                 (p_map+i)->age=i;
52         }
53 
54         if(shmdt(p_map) == -1)
55         {
56                 perror("shmdt error
");
57                 return -1;
58         }
59         return 0;
60 }

shmread.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
        char name[8];
        int age;
}people;

int main(int argc, char *argv[])
{
        int shmid;
        people *p_map;
        key_t key;
        char pathname[30];
        int i = 0;

        strcpy(pathname, "/tmp");
        key = ftok(pathname, 0x03);
        if(key == -1)
        {
                perror("ftok error
");
                return -1;
        }
        printf("key=%d
", key);
        shmid = shmget(key, 0, 0);
        if(shmid == -1)
        {
                perror("shmread:shmget error
");
                return -1;
        }
        printf("shmid=%d
",shmid);
        p_map = (people*)shmat(shmid, NULL, 0);
        for(i=0;i<3;i++)
        {
                printf("name:%s
", (*(p_map+i)).name);
                printf("age:%d
", (*(p_map+i)).age);
        }
        if(shmdt(p_map) == -1)
        {
                perror("shmdt error
");
                return -1;
        }
        return 0;
}

然后执行:

gcc shmwrite.c -o shmwrite
gcc shmread.c -o shmread
./shmwrite
./shmread
无欲速,无见小利。欲速,则不达;见小利,则大事不成。
原文地址:https://www.cnblogs.com/ch122633/p/8068152.html