关闭

Linux 多线程编程( POSIX )( 六 )----->代码区 ( 共享内存实例 )

标签: linux多线程编程nullserverstruct
1084人阅读 评论(0) 收藏 举报
分类:
注意:以下编译加上  -lrt
例如:gcc  -o server  server.c  -lrt

1.创建一个共享内存区的例子


#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>

int main( int argc, char ** argv )
{
 
   intshm_id;
   
    if( argc !=2 )
    {
      printf("请输入共享区名称!\n");
       exit(EXIT_FAILURE );
    }
   
    if( ( shm_id= shm_open( argv[1], O_CREAT | O_RDWR, 0644 ) ) <= 0)
                                      //!> 创建共享区
      printf("创建共享区失败...\n");
       exit(EXIT_FAILURE );
    }

    printf("共享区ID == %d \n", shm_id );

    shm_unlink(argv[1] );      //!> 删除共享区

    return0;
}

2.使用mmap映射将一个文件中内容cp到一个新建的文件
  注意:必须有一个现有的 old 文件


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

int main( int argc, char ** argv )
{
    int       fd_in,fd_out;      //!> 源文件和新建的文件 文件描述符
    void *src;            //!> 源
    void *des;            //!> 目的
    struct statstat_buf;      //!> 文件信息结构体
   
    if( argc !=3 )            //!> 注意参数:2个文件名
    {
      printf("请输入两个文件名!\n");
       exit(EXIT_FAILURE );
    }
   
    if( ( fd_in= open( argv[1], O_RDONLY ) ) < 0)      //!> 打开源文件
                                               //!> 只读打开
       perror(argv[1] );
    }
    if( ( fd_out= open( argv[2], O_RDWR|O_CREAT|O_TRUNC ) ) < 0)
                                               //!> 创建新文件
       perror(argv[2] );                              //!> 若文件存在,则长度被截为0,属性不变
     
   
    if( fstat(fd_in, &stat_buf ) < 0)      //!> 获取源文件信息
    {
       printf("获取源文件信息失败" );
       exit(EXIT_FAILURE );
    }
   
    if( lseek(fd_out, stat_buf.st_size - 1, SEEK_SET ) == -1 )
                                //!> 初始化输出映射存储区
      printf("lseek Error...\n");
       exit(EXIT_FAILURE );
    }
   
    if( write(fd_out, "1", sizeof( "1" )) == -1 )
    {
      printf("写入错误!\n");
       exit(EXIT_FAILURE );
    }

    if( ( src =mmap( 0, stat_buf.st_size, PROT_READ, MAP_SHARED, fd_in, 0 ) ) ==MAP_FAILED )
    {
      printf("源文件映射错误。。。");
       exit(EXIT_FAILURE );
    }
   
    if( ( des =mmap( 0, stat_buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,fd_out, 0 ) ) == MAP_FAILED )
    {
      printf("目标文件映射错误。。。\n");
       exit(EXIT_FAILURE );
    }
   
    memcpy( des,src, stat_buf.st_size);      //!> 复制
    munmap( src,stat_buf.st_size);            //!> 删除映射关系
    munmap( des,stat_buf.st_size );
   
    close( fd_in);
    close(fd_out );
   
    return0;
}

3.显示共享区信息

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>

int main( int argc, char ** argv )
{
    int       shm_id =-1;
    struct    statbuf;
   
    if( argc !=2 )
    {
      printf("请输入共享区名称!\n");
       exit(EXIT_FAILURE );
    }
   
    if( ( shm_id= shm_open( argv[1], O_RDWR | O_CREAT, 0644 ) ) == -1 )
                                         //!> 创建共享区
      printf("创建共享区失败....\n");
       exit(EXIT_FAILURE );
     

    if(ftruncate( shm_id, 100 ) != 0)            //!> 修改共享区大小
    {
      printf("修改共享区大小失败...\n");
       exit(EXIT_FAILURE );
    }
   
    if( fstat(shm_id, &buf ) != 0)               //!> 获取文件(共享区)信息
    {
      printf("获取共享区信息失败...\n");
       exit(EXIT_FAILURE );
    }
   
   printf("uid_t: %d\n", buf.st_uid);      //!> 共享内存区所有者ID
   printf("git_t: %d\n", buf.st_gid);      //!> 共享内存区所有者组ID
    printf("size: %d\n", ( int )buf.st_size);   //!> 共享内存区大小
   
    return0;
}

4.共享内存区的写入和读出

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>

int main( int argc, char ** argv )
{
   int       shm_id =-1;
    char*    ptr =NULL;
    struct   stat       buf;
   
    if( argc !=2 )
    {
      printf("请输入共享区名称!\n");
       exit(EXIT_FAILURE );
    }

    if( ( shm_id= shm_open( argv[1], O_CREAT | O_RDWR, 0644 ) ) == -1 )
                                //!> 创建共享区
      printf("创建共享区失败...\n");
       exit(EXIT_FAILURE );
    }
   
    if(ftruncate( shm_id, 100 ) != 0)   //!> 修改共享区大小
    {
       printf("修改共享区失败...\n" );
       exit(EXIT_FAILURE );
    }

    if( fstat(shm_id, &buf ) != 0 )
    {
      printf("获取共享区信息失败...\n");
       exit(EXIT_FAILURE );
    }
   
    if( ( ptr =mmap( NULL, buf.st_size, PROT_READ|PROT_WRITE,MAP_SHARED,shm_id,0 )) == MAP_FAILED )
    {
      printf("创建映射失败....\n");
       exit(EXIT_FAILURE );
    }
   
   //!> 注意,此后的ptr就是共享区首地址咯!
   
    strcpy( ptr,"Hello Linux memory map ...");   //!> 写入
   printf("输入共享区内容:%s\n", ptr);

    shm_unlink(argv[1] );   //!> 删除映射
   
    return0;
}

5.C-S模式实例

//!> cs.h


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <semaphore.h>


//!> server.c

#include "cs.h"

int main( int argc, char ** argv )
{
    int          shm_id =-1;
    sem_t*    sem;
   char     ptr;
   
    if( argc !=2 )
    {
       printf("请输入共享区名称!\n" );
       exit(EXIT_FAILURE );
    }
   
    if( ( shm_id= shm_open( argv[1], O_RDWR | O_CREAT, 0644 ) ) == -1 )
    {
      printf("创建共享区失败...\n");
       exit(EXIT_FAILURE );
    }
   
    if(ftruncate( shm_id, 100 ) != 0 )
    {
      printf("修改内存区大小失败...\n");
       exit(EXIT_FAILURE );
    }

    if( ( sem =sem_open( argv[1], O_CREAT, 0644, 1 ) ) == SEM_FAILED )
           //!> 注意此处创建的信号量在内核运行段都有效,只要不销毁
      printf("创建互斥信号量失败...\n");
       exit(EXIT_FAILURE );
    }
   
    if( ( ptr =mmap( NULL, 100, PROT_READ | PROT_WRITE, MAP_SHARED, shm_id, 0 ) )== MAP_FAILED )
    {
      printf("创建映射失败...\n");
      exit(EXIT_FAILURE);
    }
   
    strcpy( ptr,"\0" );
   
   //!> 我们分析可以知道:ptr是和共享区连到一起,那么此处其实
   //!> 就是接收client传过来的请求字符串,所以只要不是NULL和
   //!> q退出字符,那么就输出而已... ...
   
    while( 1)
    {
       if( (strcmp( ptr, "\0" ) ) == 0)         //!> 内容为空则等待
       {
         continue;
       }
       else
       {
          if( (strcmp( ptr, "q\n" ) ) == 0)   //!> q + 回车退出
          {
             break;
          }
         
          sem_wait(sem );      //!> 申请信号量
         
         printf("server: %s \n", ptr);
          strcpy( ptr,"\0" );
         
          sem_post(sem );      //!> 释放信号量
       }
      
       sem_unlink(argv[1] );      //!> 删除信号量
       shm_unlink(argv[1] );      //!> 删除共享区
      
    }
   
    return0;
}



//!> client.c


#include "cs.h"

int main( int argc, char ** argv )
{
    int          shm_id =-1;
    char*       ptr;
    sem_t*    sem;
   
    if( argc !=2 )
    {
      printf("请输入共享区名称!\n");
       exit(EXIT_FAILURE );
    }
   
    if( ( shm_id= shm_open(argv[1], O_RDWR | O_CREAT, 0644 ) ) == -1)   //!> 打开共享区
    {
      printf("打开共享区失败...\n");
       exit(EXIT_FAILURE );
    }
   
    if( ( sem =sem_open( argv[1], 0 ) ) == SEM_FAILED)   //!> 打开信号量
    {
      printf("打开信号量失败...\n");
       exit(EXIT_FAILURE );
    }


    if( ( ptr =mmap( NULL, 100, PROT_READ | PROT_WRITE, MAP_SHARED, shm_id, 0 ) )== MAP_FAILED)            //!> 链接到共享区
    {
      printf("连接映射失败...\n");
      exit(EXIT_FAILURE);
    }

    while( 1)
    {
       sem_wait(sem );      //!> 申请信号量
      
      printf("客户请求->");
       fgets( ptr,10, stdin );   //!> 从键盘读入
      printf("client: %s\n", ptr);
       if( strcmp(ptr, "q\n" ) == 0)   //!> 退出
       {
          exit(EXIT_SUCCESS );
       }
      
       sem_post(sem );      //!> 释放
       sleep( 1);
    }

    return0;
}


    结果:
   客户请求->aaa
    client:aaa
   
    server:aaa
    
   客户请求->bbb
    client:bbb
   
    server:bbb
    
   客户请求->q
    client:q

3
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Linux共享内存编程实例

转子: [cpp] view plaincopy /*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)    从而使得这些进程可以相互通信。   &#...
  • zhaoyw2008
  • zhaoyw2008
  • 2014-08-24 00:32
  • 6189

Linux进程通信之POSIX共享内存

前面已经讨论过Linux下个各种进程间的通信方式:管道,FIFO,消息队列,他们的共同特点就是通过内核来进行通信(假设POSIX消息队列也是在内核中实现的,因为POSIX标准并没有限定它的实现方式)。向管道,FIFO,消息队列写入数据需要把数据从进程复制到内核,从这些IPC读取数据的时候又需要把数据...
  • anonymalias
  • anonymalias
  • 2013-08-13 01:09
  • 6441

Linux进程间通信(IPC)编程实践(八)共享内存的使用-POSIX 共享内存(API)

1、Posix提供了两种在无亲缘关系进程间共享内存区的方法: (1)内存映射文件:先有open函数打开,然后调用mmap函数把得到的描述符映射到当前进程地址空间中的一个文件(上一篇博文所用到的就是)。 (2)共享内存区对象:先有shm_open打开一个Posix IPC名字(也可以是文件...
  • NK_test
  • NK_test
  • 2015-11-23 22:03
  • 2084

Posix多线程编程学习笔记(六)—共享内存(1)

一、什么是共享内存区 共享内存区是最快的可用IPC形式。它允许多个不相关的进程去访问同一部分逻辑内存。如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案。一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传输就不再涉及内核。这样就可以减少系统调用时间,提高程序效...
  • elbort
  • elbort
  • 2012-05-22 11:31
  • 365

Linux 多线程编程( POSIX )( 六 )----->共享内存区

转自:http://blog.sina.com.cn/s/blog_6dc9e4cf0100xeut.html 1. 介绍      POSIX 共享内存和SYSTEMV的共享内存的框架是差不多的,细节有区别!     在前面的S...
  • sweet_life
  • sweet_life
  • 2013-05-20 14:20
  • 1332

Linux 多线程编程( POSIX )( 六 )----->共享内存区

Attention:打开相关代码区 1. 介绍      POSIX 共享内存和SYSTEMV的共享内存的框架是差不多的,细节有区别!     在前面的SYSTEM V的共享内存区我们已经知道共享内存区是最快的IPC形...
  • shanshanpt
  • shanshanpt
  • 2012-03-21 06:50
  • 1757

Linux 多线程编程( POSIX )( 五 )----->代码区 ( 条件变量实例 )

1.条件变量的基本作用 //!> 条件变量的基本作用 #include #include #include //!> 注意此处为了方便就使用静态变量吧 pthread_mutex_t      ...
  • shanshanpt
  • shanshanpt
  • 2012-03-21 06:45
  • 1154

Linux 多线程编程( POSIX )( 三 )------->代码区 ( 信号灯实例 )

1.sem_open与sem_close与sem_unlink与sem_getvalue #include #include #include #include #include int main( int argc, char ** argv ) { sem_t ...
  • shanshanpt
  • shanshanpt
  • 2012-03-21 06:40
  • 1202

Posix多线程编程(6)—共享内存

一、什么是共享内存区 共享内存区是最快的可用IPC形式。它允许多个不相关的进程去访问同一部分逻辑内存。如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案。一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传输就不再涉及内核。这样就可以减少系统
  • zhouxuehua
  • zhouxuehua
  • 2011-08-09 16:12
  • 266

Posix多线程编程(6)—共享内存

一、什么是共享内存区  共享内存区是最快的可用IPC形式。它允许多个不相关的进程去访问同一部分逻辑内存。如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案。一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传输就不再涉及内核。这样就可以减少系统调用时间...
  • ruglcc
  • ruglcc
  • 2012-08-17 10:19
  • 592
    个人资料
    • 访问:618481次
    • 积分:7007
    • 等级:
    • 排名:第3819名
    • 原创:182篇
    • 转载:36篇
    • 译文:0篇
    • 评论:84条
    博客专栏