【转】Linux共享内存编程实例

时间:2014-05-12 21:28:35   收藏:0   阅读:725

原文地址:http://blog.csdn.net/pcliuguangtao/article/details/6526119

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)
  从而使得这些进程可以相互通信。
  在GNU/Linux中所有的进程都有唯一的虚拟地址空间,而共享内存应用编程接口API允许一个进程使
  用公共内存区段。但是对内存的共享访问其复杂度也相应增加。共享内存的优点是简易性。
  使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间向内核地址空间的一次复制,
  同样一个进程进行消息读取时也要进行一次复制。共享内存的优点是完全省去了这些操作。
  共享内存会映射到进程的虚拟地址空间,进程对其可以直接访问,避免了数据的复制过程。
  因此,共享内存是GNU/Linux现在可用的最快速的IPC机制。
  进程退出时会自动和已经挂接的共享内存区段分离,但是仍建议当进程不再使用共享区段时
  调用shmdt来卸载区段。
  注意,当一个进程分支出父进程和子进程时,父进程先前创建的所有共享内存区段都会被子进程继承。
  如果区段已经做了删除标记(在前面以IPC——RMID指令调用shmctl),而当前挂接数已经变为0,
  这个区段就会被移除。
 */ 
/*
  shmget(  )  创建一个新的共享内存区段
              取得一个共享内存区段的描述符
  shmctl(  )  取得一个共享内存区段的信息
              为一个共享内存区段设置特定的信息
              移除一个共享内存区段
  shmat(  )   挂接一个共享内存区段
  shmdt(  )   于一个共享内存区段的分离
 */ 
//创建一个共享内存区段,并显示其相关信息,然后删除该内存共享区 
#include <stdio.h> 
#include <unistd.h>  //getpagesize(  ) 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#define MY_SHM_ID 67483 
int main(  ) 
    
        //获得系统中页面的大小 
        printf( "page size=%d/n",getpagesize(  ) ); 
        //创建一个共享内存区段 
        int shmid,ret; 
        shmid=shmget( MY_SHM_ID,4096,0666|IPC_CREAT ); 
        //创建了一个4KB大小共享内存区段。指定的大小必须是当前系统架构 
        //中页面大小的整数倍 
        if( shmid>0 ) 
            printf( "Create a shared memory segment %d/n",shmid ); 
        //获得一个内存区段的信息 
        struct shmid_ds shmds; 
        //shmid=shmget( MY_SHM_ID,0,0 );//示例怎样获得一个共享内存的标识符 
        ret=shmctl( shmid,IPC_STAT,&shmds ); 
        if( ret==0 ) 
            
                printf( "Size of memory segment is %d/n",shmds.shm_segsz ); 
                printf( "Numbre of attaches %d/n",( int )shmds.shm_nattch ); 
            
        else 
            
                printf( "shmctl(  ) call failed/n" ); 
            
        //删除该共享内存区 
        ret=shmctl( shmid,IPC_RMID,0 ); 
        if( ret==0 ) 
            printf( "Shared memory removed /n" ); 
        else 
            printf( "Shared memory remove failed /n" ); 
        return 0; 
    
   
//共享内存区段的挂载,脱离和使用 
//理解共享内存区段就是一块大内存 
#include <stdio.h> 
#include <sys/shm.h> 
#include <sys/ipc.h> 
#include <errno.h> 
#define MY_SHM_ID 67483 
int main(  ) 
    
        //共享内存区段的挂载和脱离 
        int shmid,ret; 
        void* mem; 
        shmid=shmget( MY_SHM_ID,0,0 ); 
        if( shmid>=0 ) 
            
                mem=shmat( shmid,( const void* )0,0 ); 
                //shmat()返回进程地址空间中指向区段的指针 
                if( ( int )mem!=-1 ) 
                    
                        printf( "Shared memory was attached in our address space at %p/n",mem ); 
                        //向共享区段内存写入数据 
                        strcpy( ( char* )mem,"This is a test string./n" ); 
                        printf( "%s/n",(char*)mem ); 
                        //脱离共享内存区段 
                        ret=shmdt( mem ); 
                        if( ret==0 ) 
                            printf( "Successfully detached memory /n" ); 
                        else 
                            printf( "Memory detached failed %d/n",errno ); 
                    
                else 
                    printf( "shmat(  ) failed/n" ); 
                   
            
        else 
            printf( "shared memory segment not found/n" ); 
        return 0; 
    
/*内存共享区段与旗语和消息队列不同,一个区段可以被锁定。
  被锁定的区段不允许被交换出内存。这样做的优势在于,与其
  把内存区段交换到文件系统,在某个应用程序调用时再交换回内存,
  不如让它一直处于内存中,且对多个应用程序可见。从提升性能的角度
  来看,很重要的。
 */ 
int shmid; 
//... 
shmid=shmget( MY_SHM_ID,0,0 ); 
ret=shmctl( shmid,SHM_LOCK,0 ); 
if( ret==0 ) 
    printf( "Locked!/n" ); 
//////////////////////////////////////////////////////////////////////// 
/*使用旗语协调共享内存的例子
  使用和编译命令
  gcc -Wall test.c -o test
  ./test create
  ./test use a &
  ./test use b &
  ./test read &
  ./test remove 
 */ 
#include <stdio.h> 
#include <sys/shm.h> 
#include <sys/ipc.h> 
#include <sys/sem.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#define MY_SHM_ID 34325 
#define MY_SEM_ID 23234 
#define MAX_STRING 200 
typedef struct 
    int semID; 
    int counter; 
    char string[ MAX_STRING+1 ]; 
}MY_BLOCK_T; 
int main(int argc,char** argv) 
    
        int shmid,ret,i; 
        MY_BLOCK_T* block; 
        struct sembuf sb; 
        char user; 
        //make sure there is a command 
        if( argc>=2 ) 
            
                //create the shared memory segment and init it 
                //with the semaphore 
              if( !strncmp(argv[ 1 ],"create",6) ) 
                    
                        //create the shared memory segment and semaphore 
                        printf( "Creating the shared memory/n" ); 
                        shmid=shmget( MY_SHM_ID,sizeof( MY_BLOCK_T ),( IPC_CREAT|0666 ) ); 
                        block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); 
                        block->counter=0; 
                        //create the semaphore and init 
                        block->semID=semget(MY_SEM_ID,1,( IPC_CREAT|0666 )); 
                        sb.sem_num=0; 
                        sb.sem_op=1; 
                        sb.sem_flg=0; 
                        semop( block->semID,&sb,1 ); 
                        //now detach the segment 
                        shmdt( ( void* )block ); 
                        printf( "Create the shared memory and semaphore successuflly/n" ); 
                           
                    
                else if( !strncmp(argv[ 1 ],"use",3) ) 
                    
                        /*use the segment*/ 
                        //must specify  also a letter to write to the buffer 
                        if( argc<3 ) exit( -1 ); 
                        user=( char )argv[ 2 ][ 0 ]; 
                        //grab the segment 
                        shmid=shmget( MY_SHM_ID,0,0 ); 
                        block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); 
                           
                        /*##########重点就是使用旗语对共享区的访问###########*/ 
                        for( i=0;i<100;++i ) 
                        
                            sleep( 1 ); //设置成1s就会看到 a/b交替出现,为0则a和b连续出现 
                        //grab the semaphore 
                        sb.sem_num=0; 
                        sb.sem_op=-1; 
                        sb.sem_flg=0; 
                        if( semop( block->semID,&sb,1 )!=-1 ) 
                            
                                //write the letter to the segment buffer 
                                //this is our CRITICAL SECTION 
                                block->string[ block->counter++ ]=user; 
                                   
                                sb.sem_num=0; 
                                sb.sem_op=1; 
                                sb.sem_flg=0; 
                                if( semop( block->semID,&sb,1 )==-1 ) 
                                    printf( "Failed to release the semaphore/n" ); 
                                   
                            
                        else 
                            printf( "Failed to acquire the semaphore/n" ); 
                        
                           
                       //do some clear work 
                        ret=shmdt(( void*)block); 
                           
                    
                else if( !strncmp(argv[ 1 ],"read",4) ) 
                    
                        //here we will read the buffer in the shared segment 
                        shmid=shmget( MY_SHM_ID,0,0 ); 
                        if( shmid!=-1 ) 
                            
                                block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); 
                                block->string[ block->counter+1 ]=0; 
                                printf( "%s/n",block->string ); 
                                printf( "Length=%d/n",block->counter ); 
                                ret=shmdt( ( void*)block ); 
 
                             
                        else 
                            printf( "Unable to read segment/n" ); 
                   
                    
                else if( !strncmp(argv[ 1 ],"remove",6) ) 
                    
                        shmid=shmget( MY_SHM_ID,0,0 ); 
                        if( shmid>=0 ) 
                            
                                block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); 
                                //remove the semaphore 
                                ret=semctl( block->semID,0,IPC_RMID ); 
                                if( ret==0 ) 
                                    printf( "Successfully remove the semaphore /n" ); 
                                //remove the shared segment 
                                ret=shmctl( shmid,IPC_RMID,0 ); 
                                if( ret==0 ) 
                                    printf( "Successfully remove the segment /n" ); 
                            
                    
                else 
                    printf( "Unkonw command/n" ); 
            
        return 0; 
           
    

  

【转】Linux共享内存编程实例,布布扣,bubuko.com

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!