Linux 进程间通讯详解七
2016-12-20 17:15
351 查看
上图的一台主机服务器架构的重大缺陷是容易死锁 因为客户端,服务器都往同一消息队列中发送接收消息,假设消息队列已经满了,此时客户端无法向队列中发送消息,阻塞了, 而服务器接收完一条消息后,想向消息队列发送消息,由于消息队列已经满了,也阻塞了,此时就会死锁。
改进型的一台主机服务器架构 建立两个消息队列,一个用于客户端写入服务器接收,一个用于服务器发送客户端接收,这样则永远不会出现死锁
//本机客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <pthread.h> struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1024]; /* message data */ }; int get_msqid(const char *pathname) { if (pathname == NULL) { printf("get_msqid() params not correct !\n"); return -1; } char *pvalue1 = getenv(pathname); if (pvalue1 == NULL) { printf("getenv() failed !\n"); return -1; } key_t sendkey = ftok(pvalue1, 1); if (sendkey == -1) { perror("ftok() err"); return -1; } int msqid = msgget(sendkey, 0666 | IPC_CREAT | IPC_EXCL); if (msqid == -1) { if (errno == EEXIST) { printf("该消息队列已经存在!\n"); msqid = msgget(sendkey, 0666); } else { perror("msgget() err"); return -1; } } return msqid; } void * start_routine(void * arg) { //客户端发送消息队列 int msqid = get_msqid("SENDFILE"); struct msgbuf buf; memset(&buf, 0, sizeof(buf)); buf.mtype = 1; //数据的前4个字节存放当前进程的pid *((int *) buf.mtext) = getpid(); while (fgets(buf.mtext + 4, 1020, stdin) != NULL) { //发送消息队列 if (msgsnd(msqid, &buf, sizeof(int) + strlen(buf.mtext + 4), 0) == -1) { perror("msgsnd() err"); return NULL; } memset(buf.mtext + 4, 0, 1020); } return NULL; } int main(int arg, char * args[]) { //开启多线程 pthread_t thr1; //设置分离线程 pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&thr1, &attr, start_routine, NULL) != 0) { printf("pthread_create() failed !\n"); return -1; } //客户端接收消息队列 int msqid = get_msqid("RECVFILE"); //recv int rc = 0; struct msgbuf buf; while (1) { memset(&buf, 0, sizeof(buf)); rc = msgrcv(msqid, &buf, 1024, getpid(), 0); if (rc == -1) { perror("msgrcv() err"); break; } printf("服务器有消息到来,消息长度是%d\n",rc); fputs(buf.mtext, stdout); } return 0; }
//本机服务器 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1024]; /* message data */ }; int get_msqid(const char *pathname) { if (pathname == NULL) { printf("get_msqid() params not correct !\n"); return -1; } char *pvalue1 = getenv(pathname); if (pvalue1 == NULL) { printf("getenv() failed !\n"); return -1; } key_t sendkey = ftok(pvalue1, 1); if (sendkey == -1) { perror("ftok() err"); return -1; } int msqid = msgget(sendkey, 0666 | IPC_CREAT | IPC_EXCL); if (msqid == -1) { if (errno == EEXIST) { printf("该消息队列已经存在!\n"); msqid = msgget(sendkey, 0666); } else { perror("msgget() err"); return -1; } } return msqid; } int main(int arg, char * args[]) { /*客户端的发送消息队列,是服务器的接收消息队列*/ int send_msqid = get_msqid("RECVFILE"); if (send_msqid == -1) return -1; int recv_msqid = get_msqid("SENDFILE"); if (recv_msqid == -1) return -1; //接收消息再发送 int rc = 0; struct msgbuf recvbuf; struct msgbuf sendbuf; int pid=0; while (1) { memset(&recvbuf,0,sizeof(struct msgbuf)); memset(&sendbuf,0,sizeof(struct msgbuf)); rc = msgrcv(recv_msqid, &recvbuf, 1024, 1, 0); if(rc==-1) { perror("msgrcv() err"); return -1; } printf("客户端有数据到来!数据的长度是%d\n",rc); //解析数据 pid=*((int *)recvbuf.mtext); sendbuf.mtype=pid; strcpy(sendbuf.mtext,recvbuf.mtext+4); fputs(sendbuf.mtext,stdout); //发送 if(msgsnd(send_msqid,&sendbuf,rc-4,0)==-1) { perror("msgsnd() err"); return -1; } } return 0; }
.SUFFIXES:.c .o CC=gcc SRCS1=test01.c OBJS1=$(SRCS1:.c=.o) EXEC1=clt SRCS2=tec02.c OBJS2=$(SRCS2:.c=.o) EXEC2=ser start:$(OBJS1) $(OBJS2) $(CC) -o $(EXEC1) $(OBJS1) -lpthread $(CC) -o $(EXEC2) $(OBJS2) @echo "-------OK---------" .c.o: $(CC) -Wall -g -o $@ -c $< clean: rm -f $(OBJS1) rm -f $(OBJS2) rm -f $(EXEC1) rm -f $(EXEC2)
相关文章推荐
- linux命令
- 一个非常棒的图片 演示 iptables 与 linux的input或者nat
- linux flock使用示例代码
- C++ 中的共享库和静态库(Linux)
- Linux如何查看进程、杀死进程、启动进程等常用命令
- python3.5-centos安装
- linux 日常命令 lsof
- 基于ARM的嵌入式Linux应用程序开发
- linux 进程同步-- mutex和文件锁
- linux tar (打包.压缩.解压缩)命令说明 | tar如何解压文件到指定的目录?
- 线程同步--信号量
- Linux下配置环境变量
- 《Unix & Linux大学教程》读书笔记
- linux下写脚本时-gt是什么意思
- linux之ls -l|grep "^-"|wc -l命令
- Linux+Qt+Subversion 安装及使用说明
- esp8266环境搭建
- Linux中硬链接与软连接的区别_(转)
- Linux 命令详解
- Linux下编译LTIB时找不到zlib的解决办法