linux下使用共享内存实现客户端/服务器

原创 2015年11月21日 14:10:58

在共享内存的使用中,顾名思义,就是实现多个进程中使用同一个内存区域来实现数据的通信。这样就可以实现一个简单的客户端/服务器程序啦。
共享内存使用的函数有下面几个:

void* shmat(int shm_id , const void* shm_addr , int shmflg);
int chmctl(int shm_id , int cmd , struct shmid_ds* buf);
int shmdt(const void* shm_addr);
int shmget(key_t key , size_t size , int shmflg);

1.shmget()函数是用来创建一个共享内存区域的。和信号量一样,需要提供一个key来作为内存段的命名。
2.shmat()函数,在第一次创建共享内存的时候,它不能被任何进程访问,要想启动共享内存,就必须要连接到一个进程的地址空间。
3.shmdt()函数用来将共享内存从当前区域分离出来。
4.shmctl()函数是共享内存的控制函数

下面来看一个完整的基于共享内存的服务器/客户端的例子。在这个例子中。客户端负责创建一个共享区域,并且对里面的数据进行输出显示。在服务器端负责对共享区域进行数据的写入。

#ifndef SHM_COM_H
#define SHM_COM_H


#define TEXT_SZ 2048  //最大的文本大小

struct shared_use_st{
    int written_by_you; //控制标记
    char some_text[TEXT_SZ];  //文本缓冲区
};



#endif // SHM_COM_H

客户端:

#include <iostream>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/shm.h>
#include "shm_com.h"
using namespace std;

struct shared_use_st;

int main()
{
    //cout << "Hello World!" << endl;
    //第一个程序是消费者程序,在头文件之后,通过设置IPC_CREAT标志位的shmget调用来创建共享内存

    int running = 1;
    void* shared_memory = (void*)0;
    struct shared_use_st *shared_stuff;
    int shmid;
    srand((unsigned int )getpid());


    //创建一个共享内存
    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 attched at %X \n" , *(int*)shared_memory);


    //程序的下一部分将shared_memory分配给shared_stuff, 然后输出written_by_you中的文本。循环一直执行到哦啊written_by_you中end字符为止。sleep调用强博消费者程序在临界区多呆一会,让生产者程序等待.
    shared_stuff = (struct shared_use_st*)shared_memory;
    shared_stuff->written_by_you = 0;
    while(running){
        if(shared_stuff->written_by_you){
            printf("You wrote:%s " , shared_stuff->some_text);
            sleep(rand()%4);
            shared_stuff->written_by_you =  0;
            //如果字符中出现end字符,退出循环
            if(strncmp(shared_stuff->some_text , "end" , 3) == 0){
                running = 0;
            }

        }

    }


    //最后,分离共享内存,然后被删除.

    if(shmdt(shared_memory) == -1){

        fprintf(stderr , "shmdt failed!\n");
        exit(EXIT_FAILURE);
    }

    if(shmctl(shmid , IPC_RMID , 0) == -1){

        fprintf(stderr , "shmctl(IPC_RMID) failed!\n");
        exit(EXIT_FAILURE);

    }

   exit(EXIT_SUCCESS);


 //   return 0;
}

服务器端:

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.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 attched ad %X\n" , *(int*)shared_memory);

    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);

}

在上面代码就完成了对程序的实现。
下面就是在命令行中挂起客户端和运行服务器端的命令啦

./client &
./server

就可以实现数据在共享内存中的交互啦,很简单吧。

服务器架构设计5------通过共享内存实现0拷贝

前几篇文章,分别聊了linux的磁盘技术、cpu进程调度,还剩下内存没怎么研究,今天来聊聊服务器的0拷贝。 linux服务器,特别类似于流媒体服务器,往往涉及到大数据量的输入、分析、输出,那么一旦实现...
  • beginning1126
  • beginning1126
  • 2013年12月10日 18:57
  • 3508

服务器架构设计5------通过共享内存实现0拷贝

前几篇文章,分别聊了linux的磁盘技术、cpu进程调度,还剩下内存没怎么研究,今天来聊聊服务器的0拷贝。 linux服务器,特别类似于流媒体服务器,往往涉及到大数据量的输入、分析、输出,那么一旦实现...
  • beginning1126
  • beginning1126
  • 2013年12月10日 18:57
  • 3508

linux c之使用共享内存实现进程间通信

这篇博客有别人的也有自己改的,作为读书笔记,勿喷。 1、共享内存的介绍 共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同...
  • u011068702
  • u011068702
  • 2017年02月21日 22:24
  • 503

Windows系统服务与用户进程共享内存

通常使用CreateFileMapping的WINAPI函数可以创建共享内存,可以实现在不同进程中访问同一数据,实现通信等。但我们在其他实际编程中会遇到,服务和进程通信的情况,及系统服务与用户进程共同...
  • huanglong8
  • huanglong8
  • 2017年05月02日 23:00
  • 664

Linux共享内存编程实例

转子: [cpp] view plaincopy /*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)    从...
  • zhaoyw2008
  • zhaoyw2008
  • 2014年08月24日 00:32
  • 6175

共享内存+互斥量实现linux进程间通信

一、共享内存简介     共享内存是进程间通信中高效方便的方式之一。共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针,两个进程可以对...
  • K346K346
  • K346K346
  • 2015年03月26日 17:14
  • 4111

【Linux】进程间通信之共享内存

为什么进程间需要通信? 1、数据传输:一个进程需要将它的数据发送给另一个进程。 2、资源共享:多个进程之间享受同样的资源 3、通知事件:一个进程需要向另一个或另一组进程发送消息,通知它们发生了某种事件...
  • Scenlyf
  • Scenlyf
  • 2016年07月28日 21:04
  • 1826

LINUX共享内存使用常见陷阱与分析

所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。其他进程能把同一段共...
  • kobejayandy
  • kobejayandy
  • 2014年04月24日 23:55
  • 1209

Linux共享内存机制

共享内存区域是被多个进程共享的一部分物理内存。如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信。共享内存是进程间共享数据的一种最...
  • jikaishihuaidan
  • jikaishihuaidan
  • 2014年09月02日 16:05
  • 944

Linux共享内存(mmap详解)

mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。...
  • MJ813
  • MJ813
  • 2016年08月01日 06:47
  • 2647
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux下使用共享内存实现客户端/服务器
举报原因:
原因补充:

(最多只允许输入30个字)