设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 手机 数据 公司
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

Linux下的进程间通信:共享存储(5)

发布时间:2019-05-08 16:31 所属栏目:117 来源:Marty Kalin
导读:它将分配 ByteSize 字节的内存,在该情况下,一般为大小适中的 512 字节。 memwriter 和 memreader 程序都只从共享内存中获取数据,而不是从备份文件。系统将负责共享内存和备份文件之间数据的同步。 接着 memwrite

它将分配 ByteSize 字节的内存,在该情况下,一般为大小适中的 512 字节。memwritermemreader 程序都只从共享内存中获取数据,而不是从备份文件。系统将负责共享内存和备份文件之间数据的同步。

  • 接着 memwriter 调用 mmap 函数:

    1. caddr_t memptr = mmap(NULL, /* let system pick where to put segment */
    2. ByteSize, /* how many bytes */
    3. PROT_READ | PROT_WRITE, /* access protections */
    4. MAP_SHARED, /* mapping visible to other processes */
    5. fd, /* file descriptor */
    6. 0); /* offset: start at 1st byte */

    来获得共享内存的指针。(memreader 也做一次类似的调用。) 指针类型 caddr_tc 开头,它代表 calloc,而这是动态初始化分配的内存为 0 的一个系统函数。memwriter 通过库函数 strcpy(字符串复制)来获取后续操作的 memptr

  • 到现在为止,memwriter 已经准备好进行写操作了,但首先它要创建一个信号量来确保共享内存的排斥性。假如 memwriter 正在执行写操作而同时 memreader 在执行读操作,则有可能出现竞争条件。假如调用 sem_open 成功了:

    1. sem_t* semptr = sem_open(SemaphoreName, /* name */
    2. O_CREAT, /* create the semaphore */
    3. AccessPerms, /* protection perms */
    4. 0); /* initial value */

    那么,接着写操作便可以执行。上面的 SemaphoreName(任意一个唯一的非空名称)用来在 memwritermemreader 识别信号量。初始值 0 将会传递给信号量的创建者,在这个例子中指的是 memwriter 赋予它执行操作的权利。

  • 在写操作完成后,memwriter* 通过调用sem_post` 函数将信号量的值增加到 1:

    1. if (sem_post(semptr) < 0) ..

    增加信号了将释放互斥锁,使得 memreader 可以执行它的操作。为了更好地测量,memwriter 也将从它自己的地址空间中取消映射,

    1. munmap(memptr, ByteSize); /* unmap the storage *

    这将使得 memwriter 不能进一步地访问共享内存。

  • 示例 4. memreader 进程的源代码

    1. /** Compilation: gcc -o memreader memreader.c -lrt -lpthread **/
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #include <sys/mman.h>
    5. #include <sys/stat.h>
    6. #include <fcntl.h>
    7. #include <unistd.h>
    8. #include <semaphore.h>
    9. #include <string.h>
    10. #include "shmem.h"
    11.  
    12. void report_and_exit(const char* msg) {
    13. [perror][4](msg);
    14. [exit][5](-1);
    15. }
    16.  
    17. int main() {
    18. int fd = shm_open(BackingFile, O_RDWR, AccessPerms); /* empty to begin */
    19. if (fd < 0) report_and_exit("Can't get file descriptor...");
    20.  
    21. /* get a pointer to memory */
    22. caddr_t memptr = mmap(NULL, /* let system pick where to put segment */
    23. ByteSize, /* how many bytes */
    24. PROT_READ | PROT_WRITE, /* access protections */
    25. MAP_SHARED, /* mapping visible to other processes */
    26. fd, /* file descriptor */
    27. 0); /* offset: start at 1st byte */
    28. if ((caddr_t) -1 == memptr) report_and_exit("Can't access segment...");
    29.  
    30. /* create a semaphore for mutual exclusion */
    31. sem_t* semptr = sem_open(SemaphoreName, /* name */
    32. O_CREAT, /* create the semaphore */
    33. AccessPerms, /* protection perms */
    34. 0); /* initial value */
    35. if (semptr == (void*) -1) report_and_exit("sem_open");
    36.  
    37. /* use semaphore as a mutex (lock) by waiting for writer to increment it */
    38. if (!sem_wait(semptr)) { /* wait until semaphore != 0 */
    39. int i;
    40. for (i = 0; i < [strlen][6](MemContents); i++)
    41. write(STDOUT_FILENO, memptr + i, 1); /* one byte at a time */
    42. sem_post(semptr);
    43. }
    44.  
    45. /* cleanup */
    46. munmap(memptr, ByteSize);
    47. close(fd);
    48. sem_close(semptr);
    49. unlink(BackingFile);
    50. return 0;
    51. }

    (编辑:ASP站长网)

    网友评论
    推荐文章
      热点阅读