撸代码--类QQ聊天实现(基于linux 管道 信号 共享内存)

一:任务描述

A,B两个进程通过管道通信,像以前的互相聊天一样,然后A进程每次接收到的数据通过A1进程显示(一个新进程,用于显示A接收到的信息),A和A1间的数据传递采用共享内存,对应的有一个B1进程,用于显示B进程接收到的信息。针对A,B进程,退出时采用ctrl+c退出,当收到对应信号后,自身进程能够通过信号处理函数进行资源清理,清理后exit退出进程。(A1,B1,手动关闭即可)。界面图如下。

二:代码展示

A进程

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>

int shm_id;

struct t
{
        char buf[128];
};

struct t *p;
void hanle(int sig)
{
        shmdt(p);
        shmctl(shm_id,IPC_RMID,NULL);//删除共享内存
        printf("delete OK........\n");
        exit(0);

}

int main()
{//A进程

        signal(SIGINT,hanle);//捕捉 ctrl+c信号

        shm_id=shmget((key_t)1234,4096,0600|IPC_CREAT);
//创建了一个共享内存

//      struct t *p;
        p=(struct t*)shmat(shm_id,NULL,0);//拿到内存的指针结构体

        int f1;
        f1=open("1.fifo",O_WRONLY);//对1 打开写端

        int f2;
        f2=open("2.fifo",O_RDONLY);//对2 打开读端

        fd_set readset;
        //定义了可读集合
        int maxfd;
        maxfd=STDIN_FILENO > f2 ? STDIN_FILENO+1:f2+1;

        struct timeval check;
        check.tv_sec=1;//设置查看时间是一秒
        char buf[128];
        while(1)
        {
         FD_ZERO(&readset);//初始化
         FD_SET(STDIN_FILENO,&readset);//添加监控对象
         FD_SET(f2,&readset);
         select(maxfd,&readset,NULL,NULL,&check);//返回可读的监控对象

         if(FD_ISSET(STDIN_FILENO,&readset))
          {//如果监控到了1管道中有标准输入 那么获取到数据 写到管道中
           memset(buf,0,sizeof(buf));
           fgets(buf,sizeof(buf),stdin);
           buf[strlen(buf)-1]='\0';
           write(f1,buf,sizeof(buf));//写到管道1中

          }
         if(FD_ISSET(f2,&readset))
          {//监控到了管道2中可以读
           memset(buf,0,sizeof(buf));
           read(f2,buf,sizeof(buf));//从管道2中读到buf了
           strcpy(p->buf,buf);//将管道2中读到的buf 弄到共享内存
           printf("from 2:  %s\n",buf);
          }
         if(strcmp(buf,"bye")==0)
          {
           break;
          }

        }
        exit(0);
}

B进程

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

int shm_id;
struct t
{
        char buf[128];
};
struct t *p;
void hanle(int sig)
{
        shmdt(p);
        shmctl(shm_id,IPC_RMID,NULL);//删除共享内存
        printf("delete OK........\n");
        exit(0);

}
int main()
{//B进程

        signal(SIGINT,hanle);
         shm_id=shmget((key_t)1235,4096,0600|IPC_CREAT);

//      struct t *p;
        p=(struct t*)shmat(shm_id,NULL,0);

        int f1;
        f1=open("1.fifo",O_RDONLY);//对1 打开读端

        int f2;
     f2=open("2.fifo",O_WRONLY);//对2 打开写端

        fd_set readset;
        //定义了可读集合
        int maxfd;
        maxfd=STDIN_FILENO > f1 ? STDIN_FILENO+1:f1+1;

        struct timeval check;
        check.tv_sec=1;//设置查看时间是一秒
        char buf[128];
        while(1)
        {
         FD_ZERO(&readset);//初始化
         FD_SET(STDIN_FILENO,&readset);//添加监控对象
         FD_SET(f1,&readset);
         select(maxfd,&readset,NULL,NULL,&check);//返回可读的监控对象

         if(FD_ISSET(STDIN_FILENO,&readset))
          {//如果监控到了1管道中有标准输入 那么获取到数据 写到管道中
           memset(buf,0,sizeof(buf));
           fgets(buf,sizeof(buf),stdin);
           buf[strlen(buf)-1]='\0';
           write(f2,buf,sizeof(buf));//写到管道2中
          }
         if(FD_ISSET(f1,&readset))
          {//监控到了管道2中可以读
           memset(buf,0,sizeof(buf));
           read(f1,buf,sizeof(buf));//从管道1中读
           strcpy(p->buf,buf);//将读出的字符 放到共享内存中
           printf("from 1:  %s\n",buf);
          }
         if(strcmp(buf,"bye")==0)
          {
           break;
          }

        }
        exit(0);
}

A1进程

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>

int shm_id;
struct t
{
        char buf[128];
};
struct t *p;
void hanle(int sig)
{
        shmdt(p);
        shmctl(shm_id,IPC_RMID,NULL);//删除共享内存
        printf("delete OK........\n");
        exit(0);
}

int main()
{
         shm_id=shmget((key_t)1234,4096,0600|IPC_CREAT);
        //获得了共享内存
//      struct t *p;
        p=(struct t*)shmat(shm_id,NULL,0);//这个也拿到了
        char s[128]={0};
        while(1)
        {
        if(strcmp(s,p->buf)!=0)
        {//字符串不相同  那么就打印出来
        strcpy(s,p->buf);
        printf("from B   :%s\n",p->buf);
        }
        }

        exit(0);
}

B1进程

<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>

int shm_id;
struct t
{
        char buf[128];
};
struct t *p;
void hanle(int sig)
{
        shmdt(p);
        shmctl(shm_id,IPC_RMID,NULL);//删除共享内存
        printf("delete OK........\n");
        exit(0);

}
int main()
{
         shm_id=shmget((key_t)1235,4096,0600|IPC_CREAT);
        //获得了共享内存
//      struct t *p;
        p=(struct t*)shmat(shm_id,NULL,0);//这个也拿到了
        char s[128]={0};
        while(1)
        {
        if(strcmp(s,p->buf)!=0)
        {//字符串不相同  那么就打印出来
        strcpy(s,p->buf);
        printf("from A   :%s\n",p->buf);
        }
        }
        exit(0);
}</span><span style="font-size:18px;">
</span>

三:结果显示

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 16:14:05

撸代码--类QQ聊天实现(基于linux 管道 信号 共享内存)的相关文章

Linux编程之共享内存

Linux 支持两种方式的共享内存:System V 和 POSIX 共享内存. 1. POSIX 共享内存 1.1 POSIX 共享内存的由来 System V 共享内存和共享文件映射的不足: System V 共享内存模型使用的是键和标识符,这与标准的 UNIX I/O 模型使用文件名和描述符的做法是不一致的.这种差异意味着使用 System V 共享内存需要一整套全新的系统调用和命令. 使用一个共享文件映射来进行 IPC 要求创建一个磁盘文件,即使无需对共享区域进行持久存储也需要这样做.除

Linux IPC之共享内存C 事例

Linux IPC之共享内存 标签: linuxrandomnull工作 2011-08-25 11:52 4123人阅读 评论(0) 收藏 举报  分类: Linux(3)  读书札记(3)  版权声明:本文为博主原创文章,未经博主允许不得转载. 简介 共享内存(shared memory)是最简单的Linux进程间通信方式之一.使用共享内存,不同进程可以对同一块内存进行读写.由于所有进程对共享内存的访问就和访问自己的内存空间一样,而不需要进行额外系统调用或内核操作,同时还避免了多余的内存拷贝

Linux进程间通信—使用共享内存

Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像

Linux进程间通信--mmap()共享内存(二)

内核怎样保证各个进程寻址到同一个共享内存区域的内存页面 1.page cache及swap cache中页面的区分:一个被访问文件的物理页面都驻留在page cache或swap cache中,一个页面的所有信息由struct page来描述.struct page中有一个域为指针mapping ,它指向一个struct address_space类型结构.page cache或swap cache中的所有页面就是根据address_space结构以及一个偏移量来区分的. 2.文件与addres

Linux进程间通信--shmget()共享内存(二)

共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容.这块共享虚拟内存的页面,出现在每一个共享该页面的进程的页表中.但是它不需要在所有进程的虚拟内存中都有相同的虚拟地址. 图 共享内存映射图 象所有的 System V IPC对象一样,对于共享内存对象的获取

Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字

Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间的通信方面的侧重点有所不同.前者是对UNIX早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,其通信进程主要局限在单个计算机内:后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制.而Linux则把两者的优势都继承了下来 linux进程间通信(IPC)有几种方式

Linux 进程间共享内存 SYSTEMV

#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, int size, int shmflag) key取值为IPC_PRIVATE时,shmflag应为IPC_CREAT,则新建共享内存key取值不为IPC_PRIVATE则应为已创建的key值,shmflag不应包含IPC_CREAT和IPC_EXCL,且大小小于等于原共享内存大小成功则返回共享内存id,失败返回-1 void *shmat(int sh

Linux进程间通信——使用共享内存

下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 特别提醒:共

Linux进程间通信--mmap共享内存(一)

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入