免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1403 | 回复: 0
打印 上一主题 下一主题

Linux 系统编程 ->进程通讯 -> 共享内存 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-15 20:32 |只看该作者 |倒序浏览

先定义下 共享内存简称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
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP