- 论坛徽章:
- 0
|
先定义下 共享内存简称shm
前面已经说过 管道 消息队列 信号灯 信号 这些都是进程通讯不可缺少的元素 我只是简单的解释了 API 如何使用 权威手册还是 MAN 只是想说的一点,很多书籍资料太旧还在扯2.4 2.2 linux 2.6 了相比以前差别太大了所以好记性不如烂笔头动动熟悉下新的 API还是很有必要的 linux 让人很恼火就是 标准很多 BSD SYS V POSIX GNU扩展 无语了 如果考虑到移植建议还是采用POSIX 接口函数进入正题吧
有个概念就是进程作为OS基本单位要区分亲缘关系和非亲缘关系 比如匿名管道 命名管道 我们这里的 shm 也分成2类 大家注意下 先说命名的shm
先 man 7 shm_overview 看看man 怎么说的 不贴了
就这2个函数就搞定了 注意一点的是 shm_open 打开的是文件描述符 创建成功/打开后 会mount 到 这里
/dev/shm/name
int shm_open(const char *name, int oflag, mode_t mode);
int shm_unlink(const char *name);
贴个DEMO
/*
*
* FILE:SHM_A.c
* PURPOSE:DEMO SHM API
* AUTHOR:MASONZHANG
*
*/
/* HEADER DEFINE */
#include
#include
#include
#include
#include
#include /* For mode constants */
#include /* For O_* constants */
/* END*/
/* data struct */
#define SHM_R 0400
#define SHM_W 0200
#define DEVICE "myname"
#define ERROR_MSG(MSG) \
do{ \
perror(MSG); \
exit(EXIT_FAILURE) ; \
}while(0)
extern int
main(int argc,char * argv[]){
int fd;
if (fd=shm_open(DEVICE,O_CREAT,SHM_R | SHM_W)==-1) ERROR_MSG("SHM");
struct stat sb;
if (fstat(fd, &sb) == -1) ERROR_MSG("FSTAT");
printf("File type: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
printf("I-node number: %ld\n", (long) sb.st_ino);
printf("Mode: %lo (octal)\n",
(unsigned long) sb.st_mode);
printf("Link count: %ld\n", (long) sb.st_nlink);
printf("Ownership: UID=%ld GID=%ld\n",
(long) sb.st_uid, (long) sb.st_gid);
printf("Preferred I/O block size: %ld bytes\n",
(long) sb.st_blksize);
printf("File size: %lld bytes\n",
(long long) sb.st_size);
printf("Blocks allocated: %lld\n",
(long long) sb.st_blocks);
printf("Last status change: %s", ctime(&sb.st_ctime));
printf("Last file access: %s", ctime(&sb.st_atime));
printf("Last file modification: %s", ctime(&sb.st_mtime));
sleep(1);
if(shm_unlink(DEVICE)==-1) ERROR_MSG("SHM UNLINK");
exit(EXIT_SUCCESS);
}
简单吧就是对文件操作 还有就是用烂的 mmap 不说了 下面说下 int shmget(key_t key, size_t size, int shmflg);void *shmat(int shmid, const void *shmaddr, int shmflg);int shmdt(const void *shmaddr);int shmctl(int shmid, int cmd, struct shmid_ds *buf);size equal to the value of size rounded up to a multiple of PAGE_SIZE 这句的意思就是你申请的实际内存是PAGE_SIZE 的倍数API 使用方式在DEMO里 :)
/*
* FILE:SHM_B.c
* PURPOSE:DEMO SHM API
* AUTHOR:MASONZHANG
*
*/
/* HEADER DEFINE */
#include stdio.h>
#include stdlib.h>
#include sys/shm.h>
#include unistd.h>
#include sys/mman.h>
#include sys/stat.h> /* For mode constants */
#include fcntl.h> /* For O_* constants */
#include wait.h>
/* END*/
/* DATA STRUCT */
#define SHM_R 0400
#define SHM_W 0200
#define DEVICE "myname"
#define ERROR_MSG(MSG) \
do{ \
perror(MSG); \
exit(EXIT_FAILURE) ; \
}while(0)
struct double_buf{
int m_child;
int m_parent;
long long int m_total;
};
typedef volatile struct double_buf * g_ptr;
g_ptr golbal_ptr;
/*END*/
extern int
main(int argc,char * argv[]){
int cpid,shmid;
if(shmid=shmget(IPC_PRIVATE,sizeof *golbal_ptr,SHM_R|SHM_W)==-1)ERROR_MSG("SHMGET");
if((golbal_ptr=(g_ptr)shmat(shmid,NULL,0))==(void*)-1) ERROR_MSG("SHMAT");
cpid=fork();
if(cpid==0){
int i=0;
for(;i20;i++)
(golbal_ptr->m_child)+=1;
_exit(EXIT_SUCCESS);
}
if(cpid0) ERROR_MSG("CHILD");
/* PARENT DO JOB */
int i=0;
for(;i20;i++)
(golbal_ptr->m_parent)+=1;
int status;
do {
int w = waitpid(cpid, &status, WUNTRACED | WCONTINUED );
if (w == -1) ERROR_MSG("WAITPID");
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
int a=golbal_ptr->m_child;
int b=golbal_ptr->m_parent;
golbal_ptr->m_total=a+b;
printf(" TESTING RESULT WAS 40==%d \n",golbal_ptr->m_total);
if(shmdt(golbal_ptr)==-1)ERROR_MSG("SHMDT");
if(shmctl(shmid,IPC_RMID,NULL)==-1) ERROR_MSG("SHMCTL");
exit(EXIT_SUCCESS);
}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/94090/showart_2122270.html |
|