Linux初学,利用共享内存,有名管道,select实现两个用户之间的自由对话。

本文介绍如何利用共享内存和有名管道在多用户间实现自由对话,通过send和recv函数,结合select函数进行实时性检测,完成数据的高效传输与显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用共享内存,有名管道,select实现两个用户之间的自由对话。

原理:send1.c  send2.c  recv1.c   recv2.c 12.fifo  21.fifo

send1.c(send2.c) 为用户1(2)的发送端,负责从标准输入读入数据传递给用户2(1)和接收用户2(1)发送的数据并传递给用户1(2)的打印端recv1.c(recv2.c)打印输出。

recv1.c(recv2.c) 为用户1(2)的打印端,将用户1(2)接收到的数据打印出来。

模式关系图:


需要用select函数来轮询检测标准输入和管道的读端,保证实时性。

send1.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
typedef struct my_mem
{
	int m_lock;
	int m_unshow;
	char m_buf[128];
}mem_t,*pmem_t;
void lock(pmem_t pm)
{
	while(pm->m_lock==0)
	{
		sleep(1);
	}
	pm->m_lock=0;
}
void unlock(pmem_t pm)
{
	pm->m_lock=1;
}
int main(int argc,char *argv[])
{
	int shmid;
	char line[128];
	int fd_s,fd_r;
	int ret;
	//open fifo 12.fifo 21.fifo
	fd_s=open("./12.fifo",O_WRONLY);
	fd_r=open("./21.fifo",O_RDONLY);
	printf("fd_s:%d,fd_r:%d\n",fd_s,fd_r);
	//获取共享内存
	shmid=shmget((key_t)1234,sizeof(mem_t),IPC_CREAT);
	if(shmid==-1)
	{
		perror("shmget");
		exit(1);
	}
	pmem_t pm=shmat(shmid,NULL,0);
	pm->m_lock=1;
	pm->m_unshow=0;
	//select轮询检测标准输入和管道读端
	fd_set rds;
	struct timeval tm;
	while(1)
	{
		FD_ZERO(&rds);
		FD_SET(0,&rds);
		FD_SET(fd_r,&rds);
		tm.tv_usec=0;
		tm.tv_sec=5;
		ret=select(1024,&rds,NULL,NULL,&tm);
		if(ret==0)
		{
			continue;
		}
		else if(ret>0)
		{
			if(FD_ISSET(0,&rds))
			{
				memset(line,0,128);
				read(0,line,127);
				write(fd_s,line,strlen(line));
			}
			if(FD_ISSET(fd_r,&rds))
			{
				memset(line,0,128);
				read(fd_r,line,127);
				lock(pm);
				while(pm->m_unshow==1)
				{
					unlock(pm) ;
					sleep(1);
					lock(pm);
				}
				strcpy(pm->m_buf,line);
				pm->m_unshow=1;
				unlock(pm);
			}
		}
	}
	close(fd_s);
	close(fd_r);//关闭管道
	shmdt(pm);//共享内存段与进程空间分离
	shmctl(shmid,IPC_RMID,NULL);//删除共享内存段
	return 0;
}
recv1.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
typedef struct my_mem
{
	int m_lock;
	int m_unshow;
	char m_buf[128];
}mem_t,*pmem_t;
void lock(pmem_t pm)
{
	while(pm->m_lock==0)
	{
		sleep(1);
	}
	pm->m_lock=0;
}
void unlock(pmem_t pm)
{
	pm->m_lock=1;
}
int main(int argc,char *argv[])
{
    int shmid;
	shmid=shmget((key_t)1234,sizeof(mem_t),IPC_CREAT);
	if(shmid==-1)
	{
		perror("shmget");
		exit(1);
	}
	pmem_t pm=shmat(shmid,NULL,0);
	while(1)
	{
		lock(pm);
		while(pm->m_unshow==0)
		{
			unlock(pm);
			sleep(1);
			lock(pm);
		}
		printf("from 2:%s\n",pm->m_buf);
		pm->m_unshow=0;
		unlock(pm);
	}
	shmdt(pm);
	return 0;
}
send2.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
typedef struct my_mem
{
	int m_lock;
	int m_unshow;
	char m_buf[128];
}mem_t,*pmem_t;
void lock(pmem_t pm)
{
	while(pm->m_lock==0)
	{
		sleep(1);
	}
	pm->m_lock=0;
}
void unlock(pmem_t pm)
{
	pm->m_lock=1;
}
int main(int argc,char *argv[])
{
	int shmid;
	char line[128];
	int fd_s,fd_r;
	int ret;
	//open fifo 12.fifo 21.fifo
	fd_r=open("./12.fifo",O_RDONLY);
	fd_s=open("./21.fifo",O_WRONLY);
	printf("fd_s:%d,fd_r:%d\n",fd_s,fd_r);
	//获取共享内存
	shmid=shmget((key_t)5678,sizeof(mem_t),IPC_CREAT);
	if(shmid==-1)
	{
		perror("shmget");
		exit(1);
	}

	pmem_t pm=shmat(shmid,NULL,0);
	pm->m_lock=1;
	pm->m_unshow=0;
	//select
	fd_set rds;
	struct timeval tm;
	while(1)
	{
		FD_ZERO(&rds);
		FD_SET(0,&rds);
		FD_SET(fd_r,&rds);
		tm.tv_usec=0;
		tm.tv_sec=5;
		ret=select(1024,&rds,NULL,NULL,&tm);
		if(ret==0)
		{
			continue;
		}
		else if(ret>0)
		{
			if(FD_ISSET(0,&rds))
			{
				memset(line,0,128);
				read(0,line,127);
				write(fd_s,line,strlen(line));
			}
			if(FD_ISSET(fd_r,&rds))
			{
				memset(line,0,128);
				read(fd_r,line,127);
				lock(pm);
				while(pm->m_unshow==1)
				{
					unlock(pm) ;
					sleep(1);
					lock(pm);
				}
				strcpy(pm->m_buf,line);
				pm->m_unshow=1;
				unlock(pm);
			}
		}
	}
	close(fd_s);
	close(fd_r);
	shmdt(pm);
	shmctl(shmid,IPC_RMID,NULL);
	return 0;
}
recv2.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
typedef struct my_mem
{
	int m_lock;
	int m_unshow;
	char m_buf[128];
}mem_t,*pmem_t;
void lock(pmem_t pm)
{
	while(pm->m_lock==0)
	{
		sleep(1);
	}
	pm->m_lock=0;
}
void unlock(pmem_t pm)
{
	pm->m_lock=1;
}
int main(int argc,char *argv[])
{
    int shmid;
	shmid=shmget((key_t)5678,sizeof(mem_t),IPC_CREAT);
	if(shmid==-1)
	{
		perror("shmget");
		exit(1);
	}
    
	pmem_t pm=shmat(shmid,NULL,0);
	while(1)
	{
		lock(pm);
		while(pm->m_unshow==0)
		{
			unlock(pm);
			sleep(1);
			lock(pm);
		}
		printf("from1:%s\n",pm->m_buf);
		pm->m_unshow=0;
		unlock(pm);
	}
	shmdt(pm);
	return 0;
}

编译运行四个文件,gcc –g –o send1 send1.c   gcc –g–o send2 send2.c    gcc –g –o recv1 recv1.c     gcc –g –o recv1 recv1.c

运行结果:


这段程序还有待优化,进程退出需要在结构体中添加一个标记,来表明管道是否关闭。可以参考上一篇文章。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值