共享内存

 1 一个创建共享内存的实例
/*
下面这个例子用shmget函数创建一块共用内存,程序中在调用shmget函数时指定key的值位IPC_PRIVATE,这个参数的有意识创建一个新的内存共享区,创建成功后,使用shell命令来看当前目录系统共享内存的状态

*/ 2 #include<stdio.h> 3 #include<sys/types.h> 4 #include<sys/ipc.h> 5 #include<sys/shm.h> 6 #include<stdlib.h> 7 #define BUFSZ 4096 8 int main(void) 9 { 10 int shm_id;/*共享内存标识符*/
 1 shmget函数
 2 函数的头文件如下
 3 #include<sys/types.h>
 4 #inlcude<sys/ipc.h>
 5 #include<sys/shm.h>
 6 函数的原型如下:
 7 int shmget (key_t key,int size,int flags);
 8 
 9 函数功能:创建或者打开一个已经存在的共享内存,若成功返回共享内存ID,若失败,返回-1
10 
11 key_t是所要创建或者打开的共享内存的键值
12 size是共享内存的区域大小,只有在创建共享内存是生效
13 flag是调用的函数操作类型的,也可以用作设置共享内存的访问权限,两者通过逻辑或表示
14 参数key和flag决定了调用函数的作用
15 
16 当key的为IPC_PRIVATE时,创建一个新的共享内存,此时参数flag取值无效
17 当key不为IPC_PRIVATE时,且flag设置了IPC_CREAT位,而没有设置IPC_EXCL位,则执行操作由key决定。
18 如果key不为IPC_PRIVATE,且flag设置为IPC_CREAT和IPC_EXCL位,则只有创建共享内存的操作,参数key的取值应该与内核中已经存在的任何共享内存的键值都不相同,否则函数调用失败!
19 
20 
21 另外调用shmget函数创建一个新的共享内存时,此共享内存的shmid_ds结构被初始化。ipc_perm中的各个域被设置为相应的值。shm_lpid,shm_nattch、shm_atime、shm_dtime被初始化为0,shm_ctime被设置为系统的当前时间  这个怎么用?
 
  
11         shm_id=shmget(IPC_PRIVATE,BUFSZ,0666);
12         if(shm_id<0)
13         {
14                 printf("shmget fialed!\n");
15                 exit(1);
16         }
17         printf("Creat a shared memory segment successfully:%d \n",shm_id);
18         system("ipcs -m");
19         return 0;
20 }

共享内存的最大的不足之处在于,由于多个进程对同一块内存区域具有访问权限,各个进程之间的同步显得尤为重要。必须控制同一时刻只有一个进程对共享内存去写入数据,否则会造成数据混乱。同步问题由信号量解决。

 程序运行结果:

 1 creat a shared memory segment successfully:98306 
 2 
 3 ------ Shared Memory Segments --------
 4 key        shmid      owner      perms      bytes      nattch     status      
 5 0x00000000 65536      wangguolon 700        5998496    2          dest         
 6 0x00000000 32769      wangguolon 700        163968     2          dest         
 7 0x00000000 98306      wangguolon 666        4096       0                       
 8 
 9 ------ Semaphore Arrays --------
10 key        semid      owner      perms      nsems     
11 
12 ------ Message Queues --------
13 key        msqid      owner      perms      used-bytes   messages    

 

我们可以看到创建了一个ID为98306的共享内存。

 

写内存操作函数:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<sys/ipc.h>
 5 #include<sys/types.h>
 6 #include<sys/shm.h>
 7 #include<unistd.h>
 8 typedef struct 
 9 {
10     char name[4];
11     int age;
12 }people;
13 
14 int main(int argc,char **argv)
15 {
16     int shm_id,i;
17     char temp;
18     people *p_map;
19     if(argc!=2)
20     {
21         printf("atshm error!\n");
22         exit(1);    
23     }
24 
25     shm_id=atoi(argv[1]);//将字符串转换为整形数

 1 /*
 2 内存附加
 3 原理:当一个共享内存创建或者打开后,某个进程如果要使用该内存,必须将此内存区附加到它的地址空间,使用shmat函数
 4 
 5 头文件:
 6 #include<sys/types.h>
 7 #include<sys/ipc.h>
 8 #include<sys/shm.h>
 9 void *shmat(int shmid,const void *addr,int flag);
10 
11 
12 参数:
13 shmid 要引入的共享内存
14 addr和flag组合说明要引入的地址值:
15 
16 通常只有两种方法:
17 1.addr=0 即指向NULL,表明让内核来决定第一个可以引入的位置
18 2.add!=0 并且flag指定SHM_RND,则此段引入addr所指向的位置
19 
20 返回值:
21 若执行成功,返回指向共享内存段的指针;错误的话,返回-1.
22 
23 
24 shmat函数成功执行后,会将shmid所表示的共享内存段的shmid_ds结构的shm_nattch计算器加一。
25 
26 */
 
  

 


26 p_map=(people *)shmat(shm_id,NULL,0); 27 temp='a'; 28 for(i=0;i<10;i++) 29 { 30 temp+=1; 31 memcpy((*(p_map+i)).name,&temp,1);//将temp的值通过内存操作进行添加 32 (*(p_map+i)).age=20+i; 33 } 34
 1 /*
 2 shmdt函数
 3 作用将指定的共享内存段从当前的进程空间中脱离出去
 4 
 5 原型及头文件:
 6 #include<sys/types.h>
 7 #include<sys/ipc.h>
 8 #include<syt/shm.h>
 9 
10 int shmdt(void *addr);
11 
12 
13 执行结果:
14 成功返回0,否则返回-1
15 
16 说明:
17 此函数仅用于将共享内存区域与进程的地址空间分离,并不删除共享内存本身
18 */

 

35     if(shmdt(p_map)==-1)
36     {
37         perror("detach error!\n");
38     }
39     return 0;
40 }

 

 

读内存操作(上面的写操作写的非常详细了,在这里不再赘述)

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<unistd.h>
 5 #include<sys/types.h>
 6 #include<sys/ipc.h>
 7 #include<sys/shm.h>
 8 
 9 typedef struct
10 {
11     char name[4];
12     int age;
13 }people;
14 
15 int main(int argc,char **argv)
16 {
17     int shm_id,i;
18     people *p_map;
19     if(argc!=2)
20     {
21         printf("read atshm error!\n");
22         exit(0);
23     }
24     shm_id=atoi(argv[1]);
25     p_map=(people *)shmat(shm_id,NULL,0);
26     for(i=0;i<10;i++)
27     {
28         printf("name:%s ",(*(p_map+i)).name);
29         printf("age %d\n",(*(p_map+i)).age);
30     }
31

  

 1 /*
 2 shmctl函数
 3 
 4 原型及头文件:
 5 #include<sys/types.h>
 6 #inlcude<sys/ipc.h>
 7 #inlcude<sys/shm.h>
 8 int shmctl(int shmid,int cmd,struct shmid_ds *buf);
 9 
10 函数作用:
11 对共享内存段进行操作
12 
13 参数:
14 shmid 要操作的共享内存段的标识符
15 cmd   要对共享内存进行的操作
  取值如下:
17   IPC_STAT  取shmid所指向的内存共享段的shmid_ds结构,对参数buf指向的结构赋值
18   IPC_SET   使用buf指向的结构对sh_mid段的相关结构进行赋值,只对特定的几个域有作用 
20   IPC_RMID  删除shmid所指向的共享内存段 
22   SHM_LOCK 锁定内存共享段在内存,此命令只有超级用户才可以使用
23   SHM_UNLOCK  对内存共享段解锁,此命令只有超级用户使用
25 
26 函数的返回值:成功返回0,否则返回-1
27 */

 

    shmctl(shm_id,IPC_STAT,&shm);
      printf("%ld\n",shm.shm_segsz);

32     if(shmdt(p_map)==-1)
33     {
34         perror("detach error!\n");
35     }
36     return 0;
37 }

 程序运行:

 gcc -o write_shm write_shm.c
gcc -o read_shm read_shm.c
1
~$ ./write_shm 98306 2 ~$ ./read_shm 98306 3 name:b age 20 4 name:c age 21 5 name:d age 22 6 name:e age 23 7 name:f age 24 8 name:g age 25 9 name:h age 26 10 name:i age 27 11 name:j age 28 12 name:k age 29
13 4096

 

1 ipcrm -m 98306 删除此共享内存

 

你可能感兴趣的:(共享内存)