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

利用共享内存,有名管道,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)接收到的数据打印出来。

模式关系图:

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

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

send1.c

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
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

运行结果:

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

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


你可能感兴趣的:(Linux基础)