linux进程通信-共享内存

共享内存

  1. 共享内存的实现原理

创建共享内存、打开共享内存

映射共享内存

分享共享内存

控制共享内存

(1)shmget

函数的作用:在内核中创建共享内存

函数的原型:int shmget(key_tkey,int size,int shmflag);

函数的参数:key:键值;

size:创建的内存大小;

shmflag:标志(同open函数的权限位)

返回值:成功:共享内存标识符;

               出错-1

头文件:#include <sys/ipc.h>

                #include <sys/shm.h>

(2)shmat

函数的作用:映射共享内存,映射到各自的内存空间

函数的原型:void * shmat(intshmid,const void *shmaddr,int shmflag);

函数的参数:shmid:内存标识符

shmaddr:映射共享内存到本进程指定地址,若为NULL,则由内核自动分配

shmflag:SHM_RDONLY:共享内存只读

                0:共享内存可读写

返回值:成功:被映射的段地址;

                出错-1

头文件:#include <sys/ipc.h>

                #include <sys/shm.h>

(3)shmdt

函数的作用:撤销共享内存的映射

函数的原型:int shmat(constvoid *shmaddr);

函数的参数:shmaddr:被映射的共享内存的地址

返回值:成功0;

                出错-1

头文件:#include <sys/ipc.h>

                #include <sys/shm.h>

 

  2.共享内没有血缘关系之间如何通信?通过设置相同的键值。程序如下

shm1.c

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"

int main()
{
    int running = 1;
    void *shared_memory = (void *)0;
    struct shared_use_st *shared_stuff;   
    int shmid;

    //创建共享内存
    shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);

    if(shmid == -1)
    {
        fprintf(stderr, "shmget failed\n");
	exit(EXIT_FAILURE);
    }

    //映射共享内存
    shared_memory = shmat(shmid, (void *)0, 0);

    if(shared_memory == (void *)-1)
    {
        fprintf(stderr, "shmat failed\n");
	exit(EXIT_FAILURE);
    }

    printf("Memory attached at %X\n", (int)shared_memory);

    //让结构体指针指向这块共享内存
    shared_stuff = (struct shared_use_st *)shared_memory;

    //控制读写顺序
    shared_stuff->written_by_you = 0;

    //循环的从共享内存中读数据,直到读到end为止
    while(running)
    {
        if(shared_stuff->written_by_you)
	{
	    printf("You wrote:%S\n", shared_stuff->some_text);
	    sleep(1);//读进程一秒,同时会导致写进程睡一秒,这样做到读了之后再写
	    shared_stuff->written_by_you = 0;

	    if(strncmp(shared_stuff->some_text, "end", 3) == 0)
	    {
	        running = 0;//结束循环
	    }
	}
    }

    //删除共享内存
    if(shmdt(shared_memory) == -1)
    {
        fprintf(stderr, "shmdt failed!\n");
	exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);

}
shm2.c

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"

int main()
{
    int running = 1;
    void *shared_memory = (void *)0;
    struct shared_use_st *shared_stuff;
    char buffer[BUFSIZ];
    int shmid;

    //创建共享内存
    shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);

    if(shmid == -1)
    {
        fprintf(stderr, "shmget failed\n");
	exit(EXIT_FAILURE);
    }

    //映射共享内存
    shared_memory = shmat(shmid, (void *)0, 0);

    
    if(shared_memory == (void *)-1)
    {
        fprintf(stderr, "shmat failed\n");
	exit(EXIT_FAILURE);
    }

    printf("Memory attached at %X\n", (int)shared_memory);

    //循环的向共享内存中写数据,直到写入的为end为止
    shared_stuff = (struct shared_use_st *)shared_memory;

    while(running)
    {
        while(shared_stuff->written_by_you == 1)
	{
	    sleep(1);//等到读进程完之后再写
	    printf("Waiting for client...\n");
	}

	printf("Enter some text:");
	fgets(buffer, BUFSIZ, stdin);
	strncpy(shared_stuff->some_text, buffer, TEXT_SZ);
	shared_stuff->written_by_you = 1;

	if(strncmp(buffer, "end", 3) == 0)
	{
	    running = 0;//结束循环
	}
	
    }

    //删除共享内存
    if(shmdt(shared_memory) == -1)
    {
        fprintf(stderr, "shmdt failed!\n");
	exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);

}
运行结果如下:



shmem.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define PERM S_IRUSR|S_IWUSR
/* 共享内存 */

int main(int argc,char **argv) 
{ 
	int shmid; 
	char *p_addr,*c_addr; 
	
	if(argc!=2) 
	{ 
		fprintf(stderr,"Usage:%s\n\a",argv[0]); 
		exit(1); 
	}

	/* 创建共享内存 */	
	if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1) 
	{ 
		fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno)); 
		exit(1); 
	} 

	/* 创建子进程 */
	if(fork()) // 父进程写
	{ 
		p_addr=shmat(shmid,0,0); 
		memset(p_addr,'\0',1024); 
		strncpy(p_addr,argv[1],1024);
		wait(NULL); // 释放资源,不关心终止状态
		exit(0); 
	} 
	else       // 子进程读
	{ 
		sleep(1); // 暂停1秒		
		c_addr=shmat(shmid,0,0); 
		printf("Client get %s\n",c_addr); 
		exit(0); 
	} 
} 
运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值