当前位置: 首页 > article >正文

linux_c IPC消息队列练习

练习题要求:

要求通过IPC的消息队列,实现两个进程之间通讯功能(通过命令行终端)

实现代码:

1.main.c

int main(int argc, const char *argv[])
{
	//存放线程调用的变量(qid,sendType,recvType)
	thread_info_t param;
	//校验参数
	if(checkArgs(&param,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, &param)!=0){
		perror("发送线程创建失败");
		return -1;
	}
	
	//配置数据接收线程
	pthread_t t2;
	if(pthread_create(&t2, NULL, taskRecv, &param)!=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信号完成了实现。


http://www.kler.cn/news/363521.html

相关文章:

  • 当数据遇到威胁:强化治理以抵御网络攻击
  • 编辑器、节点树、基础设置
  • [分享] SQL在线编辑工具(好用)
  • grafana failed to load dashboard from file= ... json error=EOF
  • 21、基于Firefly-rk3399字符设备驱动寄存器控制LED
  • SSL证书有免费的吗?在哪里可以申请到?——附带申请步骤
  • OpenHarmony 目前所有体系详细介绍
  • Git的多人协作模式与企业级开发模型
  • 【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (三):Cors的设置及.env文件的设置
  • 2024年03月中国电子学会青少年软件编程(图形化)等级考试试卷(四级)答案 + 解析
  • java字段判空方法Assert.hasText()详细讲解
  • 智慧城市垃圾分类可视化
  • 提示词高级阶段学习day3.1什么是结构化 Prompt ?
  • 算法魅力-双指针之滑动窗口的叛逆
  • 吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)3.9-3.10
  • 【vue + mockjs】Mockjs——数据接口模拟
  • git clone卡在Receiving objects
  • matlab生成mipi crc值
  • MySQL 中的连表是怎样实现的?为什么大厂不使用连表查询?
  • Python 文件路径与文件系统操作
  • springboot RedisTemplate支持多个序列化方式
  • MacOS RocketMQ安装
  • 「AIGC」AI设计工具Polymet
  • mac m1 git clone 忽略大小写敏感
  • Linux 部署 Harbor 镜像仓库详解
  • 数据库、数据仓库、数据湖和数据中台有什么区别