linux_c IPC消息队列练习
练习题要求:
要求通过IPC的消息队列,实现两个进程之间通讯功能(通过命令行终端)
实现代码:
1.main.c
int main(int argc, const char *argv[])
{
//存放线程调用的变量(qid,sendType,recvType)
thread_info_t param;
//校验参数
if(checkArgs(¶m,argc, argv)==-1){
return -1;
}
//创建消息队列
int qid=createMsgQueue();
param.qid=qid;
if(qid == -1){
perror("create msg queue error");
return -1;
}
//配置数据发送线程
pthread_t t1;
if(pthread_create(&t1, NULL, taskSend, ¶m)!=0){
perror("发送线程创建失败");
return -1;
}
//配置数据接收线程
pthread_t t2;
if(pthread_create(&t2, NULL, taskRecv, ¶m)!=0){
perror("接收线程创建失败");
return -1;
}
//销毁线程
pthread_join(t1, NULL);
pthread_join(t2, NULL);
//销毁消息队列
msgctl(qid, IPC_RMID, NULL);
printf("程序执行完成\n");
return 0;
}
2.chat.h
typedef struct{
long mtype;
char mtext[256];
}msg_t;
typedef struct{
int qid;//消息队列的id
long sendType;//发送消息的type
long recvType;//接收消息的type
}thread_info_t;
#define TEXT_SIZE (sizeof(msg_t)-sizeof(long))
int createMsgQueue();
void* taskSend(void* arg);
void* taskRecv(void* arg);
int checkArgs(thread_info_t *p,int argc,const char* argv[]);
3.chat.c
int createMsgQueue(){
//ftok 拿key
key_t key=ftok("/", 111);
if(key == -1){
perror("ftok error");
return -1;
}
printf("key=[%#X]\n", key);
//获取queue的id
int qid=msgget(key, IPC_CREAT | 0664);
if(qid==-1){
perror("msgget error");
return -1;
}
return qid;
}
void* taskSend(void* arg){//qid, msgtype
thread_info_t* param=(thread_info_t*)arg;
msg_t msg;
msg.mtype=param->sendType;
while(1){
printf("输入消息>>");
fflush(stdout);
fgets(msg.mtext,TEXT_SIZE,stdin);
msg.mtext[strlen(msg.mtext)-1]=0;
//向队列发送消息
if(-1==msgsnd(param->qid, &msg, TEXT_SIZE, 0)){
perror("msgsnd error");
break;
}
if(strcmp("quit", msg.mtext) ==0){
raise(SIGKILL);
break;
}
}
pthread_exit(NULL);
}
void* taskRecv(void* arg){
thread_info_t* param=(thread_info_t*)arg;
msg_t msg;
msg.mtype=param->recvType;
while(1){
int cnt=msgrcv(param->qid,&msg,TEXT_SIZE,param->recvType, 0);
if(cnt ==-1){
perror("msgrcv");
break;
}
printf("收到:%s\n", msg.mtext);
if(strcmp("quit",msg.mtext)==0){
raise(SIGKILL);
break;
}
}
pthread_exit(NULL);
}
int checkArgs(thread_info_t *p,int argc, const char* argv[]){
if(argc != 3){
fprintf(stderr,"输入参数过少\n");
return -1;
}
sscanf(argv[1],"%ld",&p->sendType);
sscanf(argv[2],"%ld",&p->recvType);
return 0;
}
运行效果:
小进步:
对比昨天的pipe的练习,最后无法关闭多线程程序,通过SIGKILL信号完成了实现。