• IPC通信:Posix共享内存2


    Posix共享内存区涉及两个步骤:

    1、指定一个名字参数调用shm_open,以创建一个新的共享内存区对象或打开一个以存在的共享内存区对象。

    2、调用mmap把这个共享内存区映射到调用进程的地址空间。传递给shm_open的名字参数随后由希望共享该内存区的任何其他进程使用。

    相关函数:

     1 shm_open()函数
     2 功能:    打开或创建一个共享内存区
     3 头文件:    #include <sys/mman.h>
     4 函数原形:    int shm_open(const char *name,int oflag,mode_t mode);
     5 返回值:    成功返回0,出错返回-1
     6 参数:    
     7     name    共享内存区的名字
     8     oflag    标志位
     9     mode    权限位
    10 
    11 参数解释:oflag参数必须含有O_RDONLY和O_RDWR标志,还可以指定如下标志:O_CREAT,O_EXCL或O_TRUNC.mode参数指定权限位,
    12 它指定O_CREAT标志的前提下使用。shm_open的返回值是一个整数描述字,它随后用作mmap的第五个参数。
    13 
    14 shm_unlink()函数
    15 功能:    删除一个共享内存区
    16 头文件:    #include <sys/mman.h>
    17 函数原形:    int shm_unlink(const char *name);
    18 参数:     name    共享内存区的名字
    19 返回值:    成功返回0,出错返回-1
    20 
    21 shm_unlink函数删除一个共享内存区对象的名字,删除一个名字仅仅防止后续的open,mq_open或sem_open调用取得成功。

    示例代码:

     1 /*shm_open.c创建共享内存区*/
     2 #include <stdlib.h>
     3 #include <sys/mman.h>
     4 #include <stdio.h>
     5 #include <fcntl.h>
     6 
     7 int main(int argc,char **argv)
     8 {
     9     int shm_id;
    10 
    11     if(argc!=2)
    12     {
    13         printf("usage:shm_open <pathname>\n");
    14         exit(1);
    15     }
    16     shm_id=shm_open(argv[1],O_RDWR|O_CREAT,0644);
    17     printf("shmid:%d\n",shm_id);
    18     shm_unlink(argv[1]);
    19 }

    编译运行:

     1 root@linux:/mnt/hgfs/C_libary# vi shm_open.c
     2 root@linux:/mnt/hgfs/C_libary# gcc -o shm_open shm_open.c
     3 /tmp/cceAejzp.o: In function `main':
     4 shm_open.c:(.text+0x43): undefined reference to `shm_open'
     5 shm_open.c:(.text+0x6c): undefined reference to `shm_unlink'
     6 collect2: ld returned 1 exit status
     7 root@linux:/mnt/hgfs/C_libary# gcc -lrt -o shm_open shm_open.c
     8 root@linux:/mnt/hgfs/C_libary# ./shm_open shm_test
     9 shmid:3
    10 root@linux:/mnt/hgfs/C_libary# 

    相关函数2:

     1 ftruncate()函数 3 功能:    调整文件或共享内存区大小
     4 头文件:    #include <unistd.h>
     5 函数原形:    int ftruncate(int fd,off_t length);
     6 参数:    
     7     fd          描述符
     8     length       大小
     9 返回值:    成功返回0,出错返回-1
    10 
    11 当打开一个已存在的共享内存区对象时,我们可调用fstat来获取有关该对象的信息
    12 
    13 fstat()函数
    14 功能:    获得文件或共享内存区的信息
    15 头文件:    #include <unistd.h>
    16 #include <sys/types.h>
    17 #include <sys/stat.h>
    18 函数原形:    int stat(const char *file_name,struct stat *buf);
    19 参数:    
    20 file_name          文件名
    21 buf               stat结构
    22 返回值:    成功返回0,出错返回-1
    23 
    24 对于普通文件stat结构可以获得12个以上的成员信息,然而当fd指代一个共享内存区对象时,只有四个成员含有信息。
    25 struct stat{
    26     mode_t st_mode;
    27     uid_t st_uid;
    28     gid_t st_gid;
    29     off_t st_size;
    30 };

    示例代码:

     1 /*shm_show.c显示共享区信息*/
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <unistd.h>
     5 #include <sys/stat.h>
     6 #include <sys/types.h>
     7 #include <fcntl.h>
     8 #include <sys/mman.h>
     9 
    10 int main(int argc,char **argv)
    11 {
    12     int shm_id;
    13         struct stat buf;
    14 
    15         if(argc!=2)
    16         {
    17             printf("usage:shm_open <pathname>\n");
    18             exit(1);
    19         }
    20         shm_id=shm_open(argv[1],O_RDWR|O_CREAT,0644);/*创建共享内存*/
    21         printf("size :%d\n",buf.st_size); /*修改前共享内存区大小*/
    22         ftruncate(shm_id,100);/*修改共享内存的大小*/
    23         fstat(shm_id,&buf); /*把共享内存的信息记录到buf中*/
    24         printf("uid_t:%d\n",buf.st_uid); /*共享内存区所有者ID*/
    25         printf("git_t:%d\n",buf.st_gid); /*共享内存区所有者组ID*/
    26         printf("size :%d\n",buf.st_size); /*修改后共享内存区大小*/
    27 }

    编译运行:

     1 root@linux:/mnt/hgfs/C_libary# gcc -lrt -o shm_show shm_show.c
     2 shm_show.c: In function ‘main’:
     3 shm_show.c:20: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘__off_t’
     4 shm_show.c:25: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘__off_t’
     5 
     6 /* 内容来自互联网
     7         有人提出来在sys/types.h里面加上 typedef long __off_t; typedef long __time_t; 
     8         
     9         小鱼我看了一下源文件,认为上面的说法还是有问题的,露了off_t和time_t
    10         #ifndef __off_t_defined 
    11         # ifndef __USE_FILE_OFFSET64 
    12         typedef __off_t off_t; 
    13         # else 
    14         typedef __off64_t off_t; 
    15         # endif 
    16         # define __off_t_defined 
    17         #endif  
    18         
    19         如果定义了__USE_FILE_OFFSET64 就把off_t定义为__off64_t ,否则定义为32位(传说中的大文件支持处理) 
    20         ------------------------------
    21         其实没必要casting。直接用%ld换掉%d就行了,因为是long int所以%d会抛警告的 
    22 */
    23 root@linux:/mnt/hgfs/C_libary# gcc -lrt -o shm_show shm_show.c
    24 root@linux:/mnt/hgfs/C_libary# 
    25 root@linux:/mnt/hgfs/C_libary# ./shm_show test
    26 size :4983648
    27 uid_t:0
    28 git_t:0
    29 size :100
    30 root@linux:/mnt/hgfs/C_libary# 

    共享内存区的写入和读出

      前面我们介绍了mmap函数,下面我们就可以通过这些函数,把进程映射到共享内存区。然后我们就可以通过共享内存区进行进程间通信了。

    示例代码:

     1 /*shm_write.c写入/读出共享内存区*/
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <sys/stat.h>
     6 #include <fcntl.h>
     7 #include <sys/mman.h>
     8 #include <unistd.h>
     9 
    10 int main(int argc,char **argv)
    11 {
    12     int shm_id;
    13     struct stat buf;
    14     char *ptr;
    15 
    16     if(argc!=2)
    17     {
    18         printf("usage:shm_open <pathname>\n");
    19         exit(1);
    20     }
    21     shm_id=shm_open(argv[1],O_RDWR|O_CREAT,0644);/*创建共享内存区*/
    22     ftruncate(shm_id,100);/*修改共享区大小*/
    23     fstat(shm_id,&buf);
    24     ptr=mmap(NULL,buf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,shm_id,0);/*连接共享内存区*/
    25     strcpy(ptr,"hello linux");/*写入共享内存区*/
    26     printf("%s\n",ptr);/*读出共享内存区*/
    27     shm_unlink(argv[1]);/*删除共享内存区*/
    28 }

    编译运行:

    1 root@linux:/mnt/hgfs/C_libary# gcc -lrt -o shm_write shm_write.c
    2 root@linux:/mnt/hgfs/C_libary# ./shm_write test
    3 hello linux
    4 root@linux:/mnt/hgfs/C_libary# 

      至此进程间通讯内容先告一段落!

  • 相关阅读:
    ckeditor 上传图片
    过滤html else <p>
    目录遍历
    android小知识之SparseArray(HaspMap替换)
    android小知识之邮箱地址输入自动完成
    android小知识之EditText输入框之值监控以及类型限制(数字,英语字母,下划线,是否为星号密码)
    android小知识之圆角ListView
    android小知识之多个listview在同一界面只有item高亮
    如何取消一个本地svn目录与svn的联系(即恢复原有图标等)
    android小知识之意图(intent)
  • 原文地址:https://www.cnblogs.com/polestar/p/2466022.html
Copyright © 2020-2023  润新知