V7.0_增加消息队列功能

news2024/10/6 4:07:41

一,功能描述

增加消息队列;使用自定义copy功能时,子进程copy结束后向父进程发送消息(通过消息队列)然后exit;此时因wait()而处于阻塞态的父进程终于解除了阻塞并且从队列中读取到消息;

增加的功能和运行结果如下:

 

二,代码如下

main.c


#include "./io.h"

struct CMD_input CMD_test1={"creat","copy","display","delete","write","ls"};
struct buffer_param *p;

int main(int argc,char **argv)
{
    //printf("argc :%d,argv[0]:%s,argv[1]:%s,argv[2]:%s\r\n",argc,argv[0],argv[1],argv[2]);
    //agrc指在终端输入的个数
    //argv[0]是第1个参数;
    //argv[1]是第二个参数;,,,,,,
    
    //1-function:解析参数1。判断要做什么操作
    //当前只接解析“creat”,但是预留“cp”,"display","delete"接口
    
    p = ( struct buffer_param *)malloc(sizeof(struct buffer_param));
    memset(p,0,sizeof(struct buffer_param));
    strncpy(p->buffer_param0,argv[0],strlen(argv[0]));
    strncpy(p->buffer_param1,argv[1],strlen(argv[1]));
    //strncpy(p->buffer_param2,argv[2],strlen(argv[2]));
    if(argc==3)
    {
        strncpy(p->buffer_param2,argv[2],strlen(argv[2]));
    }
    else if(argc==4)
    {
        strncpy(p->buffer_param3,argv[3],strlen(argv[3]));
    }
    


    log_test1();//打印所有参数
    read_CMD();//读取指令“creat,write,delete,display,copy”
    task_sch();//执行任务




    return 0;
}





 io.c

#include "./io.h"
#include "./ipc.h"
extern struct buffer_param *p;
extern struct CMD_input CMD_test1;
int flag_of_QUITEDIT=0;
char path_of_file[30];
char flag_of_key_event=0;
int fd_for_creat_file[2];//pipe
int fd_for_write_file=0;
void log_test1()
{
    printf("param0:%s\r\n",p->buffer_param0);
    printf("param1:%s\r\n",p->buffer_param1);
    printf("param2:%s\r\n",p->buffer_param2);
    printf("param3:%s\r\n",p->buffer_param3);
}
int read_CMD()
{
    if(strncmp(p->buffer_param1,CMD_test1.CMD_CREAT,strlen(p->buffer_param1))==0)//creat
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"./%s",p->buffer_param2);
        flag_of_key_event = Key_event_creatFile;
        //creat(buffer_param2, S_IRWXU);
    }
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_WRITE,strlen(p->buffer_param1))==0)//write
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"./%s",p->buffer_param2);
        flag_of_key_event = Key_event_writeFile;///写入数据
    }    
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_DISPLAY,strlen(p->buffer_param1))==0)//display
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"cat ./%s",p->buffer_param2);
        flag_of_key_event = Key_event_displayFile;///
    } 
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_CP,strlen(p->buffer_param1))==0)//copy
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"cp ./%s ./%s",p->buffer_param2,p->buffer_param3);
        flag_of_key_event = Key_event_copyFile;///
    } 
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_DELETA,strlen(p->buffer_param1))==0)//display
    {
        memset(path_of_file,0,sizeof(path_of_file));
        sprintf(path_of_file,"rm ./%s",p->buffer_param2);
        flag_of_key_event = Key_event_deleteFile;///
    }
    
    else if(strncmp(p->buffer_param1,CMD_test1.CMD_LS,strlen(p->buffer_param1))==0)//ls
    {
        memset(path_of_file,0,sizeof(path_of_file));

        flag_of_key_event = Key_event_LSFile;///
    }     
    return 0;
}
                
int task_sch()
{
    int return_of_fork;
    int status_childProcess=0;//子进程退出状态
    switch(flag_of_key_event)
    {
        case Key_event_creatFile: //读管道+写管道
//
                my_pipe_for_creat_file();//创建无名管道;子进程处理完任务后,通过pipe通知父进程
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    creat_file();
                else if(return_of_fork>0)
                    //通过管道读数据
                    creat_file_father_process_read_notify_from_pipe();
                    wait(NULL);
            break;
        case Key_event_writeFile:
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    write_file();
                else if(return_of_fork>0)
                    my_fifo_for_write_file();//通过fifo实现父子进程间的通信
                    //wait(&status_childProcess);
                    //printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));
            break;
        case Key_event_displayFile:            
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    display_file();
                else if(return_of_fork>0)
                    wait(&status_childProcess);
                    printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));
            break;
        case Key_event_copyFile:
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    copy_file();
                else if(return_of_fork>0)
                    wait(&status_childProcess);
                    get_msg_from_queue();
                    printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));

            break;
        case Key_event_deleteFile:
                return_of_fork = fork();//创建1个子进程
                if(return_of_fork<0)
                    printf("creat childprocess failed\r\n");
                else if(return_of_fork==0)
                    delete_file();
                else if(return_of_fork>0)
                    wait(&status_childProcess);
                    printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));
            break;
        case Key_event_LSFile :
                ls_file();
                break;

        default :break;
    }
}

int creat_file()//在子进程中完成创建文件
{
    int ret=0;
    ret = creat(p->buffer_param2, S_IRWXU);//
    if(ret==-1)
    {
        printf("creat file failed\r\n");
    }
    //创建完成后,子进程通过管道通知父进程“创建完成”
    creat_file_child_process_notify_father_process();
    exit(Key_event_creatFile);//退出子进程
    return ret;

}


int write_file()
{
    int ret=0;
    int fd=0;
    char readbuffer[128]={0};
    fd = open(path_of_file,O_RDWR | O_CREAT,0666) ;
    if(fd == -1)
	{
		printf("unexist %s\n",path_of_file);
	}	
	else
	{
		printf("open file success\n");
        printf("if you want exit edit ,please input “QUIT”\r\n");
        printf("please input string :\r\n");

        while(flag_of_QUITEDIT==0)
        {

            printf(">");
            memset(readbuffer,0,sizeof(readbuffer));
            fgets(&readbuffer[0],50,stdin);
            
            if(strncmp(readbuffer,"QUIT",strlen("QUIT"))==0)
            {
                flag_of_QUITEDIT=1;
            }
            //add"enter"to string
            {
                int len;
                len = strlen(readbuffer);
                readbuffer[len] = '\n';
                readbuffer[len+1] = '\0';
            }

            
            ret = write(fd,readbuffer,strlen(readbuffer));
            if(ret == -1)
            {
                perror("write");
                exit(-1);
            }
            if(flag_of_QUITEDIT==1)
            {
                close(fd);
                write_file_child_process_notify_father_process_by_fifo();
                exit(Key_event_writeFile);
            }
        }

        }
}


int display_file()
{
    int fd=0;
    //fd = system(path_of_file);
    //printf("fd = %d\r\n",fd);
    fd = execl_for_cat();
    if(fd>0)
    {
        printf("cat file failed\r\n");
    }
    close(fd);
    //exit(Key_event_displayFile);
}

int copy_file()
{
    int fd=0;
    int fdSRC=0;
    int fdDES=0;
    char *readBuf = NULL;
    //fd = system(path_of_file);
    //printf("fd = %d\r\n",fd);
    //使用lseek实现copy;源文件:p->buffer_param2;目标文件:p->buffer_param3
    fdSRC = open(p->buffer_param2,O_RDWR);//打开文件
    if(fdSRC==-1)
    {
        printf("src open failed\r\n");
    }
    else{
        //源文件打开成功
        int size = lseek(fdSRC,0,SEEK_END);//读取文件大小
        lseek(fdSRC,0,SEEK_SET);//把光标移动到文件头部
        readBuf = (char *)malloc(sizeof(char)*size + 8);//指针指向这么大的空间
        int n_read = read(fdSRC, readBuf, 1024);//把源文件的数据读取到buffer中

        fdDES = open(p->buffer_param3,O_RDWR|O_CREAT,0600);//创建目标文件
        int n_write = write( fdDES,readBuf,strlen(readBuf));//向目标文件写入信息
        close(fdSRC);
	    close(fdDES);
        send_msg_to_queue();
 	    exit(Key_event_copyFile);
    }


    
}


int delete_file()
{
    int fd=0;
    fd = system(path_of_file);



    exit(Key_event_deleteFile);
}


int execl_for_cat()
{
    memset(path_of_file,0,sizeof(path_of_file));
    sprintf(path_of_file,"./%s",p->buffer_param2);
    printf("will display file by execl \r\n");

    if(execl("/bin/cat","cat",path_of_file,NULL) == -1)//exec族函数中的函数调用失败时会设置error并返回-1,然后从源程序调用点接着往下执行。执行成功后不会返回,也不会从源程序调用点接着往下执行。
	{
		printf("exec failed\n");
	}
    //return 0;
}



int ls_file()//使用这个功能时:./a.out ls xxx(第3个参数随便填)
{

	char return_buffer[1024] = {0};
	FILE *fp;
	fp = popen("ls","r");

	int nread = fread(return_buffer,1,1024,fp);
	printf("return_buffer %d byte,\nbuffer:%s\n",nread,return_buffer);

    exit(Key_event_LSFile);
}

 io.h

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>

#define Key_event_creatFile 0x01
#define Key_event_writeFile 0x02
#define Key_event_displayFile 0x03
#define Key_event_copyFile 0x04
#define Key_event_deleteFile 0x05
#define Key_event_LSFile 0x06
struct CMD_input{
    char CMD_CREAT[10];
    char CMD_CP[10];
    char CMD_DISPLAY[10];
    char CMD_DELETA[10];
    char CMD_WRITE[10];
    char CMD_LS[10];
};

struct buffer_param{
    char buffer_param0[10];
    char buffer_param1[10];
    char buffer_param2[10];
    char buffer_param3[10];
};
void log_test1();
int read_CMD();
int task_sch();
int creat_file();
int write_file();
int display_file();
int copy_file();
int delete_file();
int execl_for_cat();
int ls_file();

 ipc.c

#include "./ipc.h"

extern int fd_for_creat_file[2];
static int ret_pipe;
char *writebuff = "childProcess had finished task for creat file\n";
char readbuff[50];


/// @brief ///pipe///
void my_pipe_for_creat_file()
{
	int pid;	
	ret_pipe = pipe(fd_for_creat_file);//创建成功则返回值为0
}

void creat_file_child_process_notify_father_process()
{
    if(ret_pipe == 0)//如果管道创建成功
    {
      close(fd_for_creat_file[0]);//关闭读通道
      write(fd_for_creat_file[1],writebuff,strlen(writebuff));//通过管道写数据
    }
    else{
        printf("pipe creat failed\r\n");
    }
}

void creat_file_father_process_read_notify_from_pipe()
{
    if(ret_pipe == 0)//如果管道创建成功
    {
      close(fd_for_creat_file[1]);//关闭写通道
      read(fd_for_creat_file[0],readbuff,strlen(writebuff));//通过管道读数据
      printf("readbuff:%s\n",readbuff);
    }
    else{
        printf("pipe creat failed\r\n");
    }

}
/// @brief ///pipe///





//fifo
//利用阻塞和解除阻塞实现通信
char buffer_for_use_fifo_notify[60]={0};
extern int fd_for_write_file;
void my_fifo_for_write_file()//父进程调用这个,让父进程处于阻塞状态
{ 
  if((mkfifo("./fifo_for_write_file",0600) == -1) && errno != EEXIST)//errno 是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定义
    {
      printf("mkfifo failed\n");
      perror("why");
    }
    fd_for_write_file=open("./fifo_for_write_file",O_RDONLY);//以只读的方式打开fifo会阻塞;需要另一个进程以只写的方式打开fifo才能解除阻塞
    printf("open success\n");
    int nread = read(fd_for_write_file,buffer_for_use_fifo_notify,30);
    printf("nread = %d,read_buffer:%s",nread,buffer_for_use_fifo_notify);
    printf("\n");
    close(fd_for_write_file);

}


void write_file_child_process_notify_father_process_by_fifo()
{
    char buffer_write[30] = {0};
    int fd = open("./fifo_for_write_file",O_WRONLY);
    printf("child process had open fifo\n");
    printf("please input data to fifo\n");
    scanf("%s",buffer_write);
    write(fd,buffer_write,strlen(buffer_write));
    close(fd);


}

//fifo





queue消息队列///
struct Queue_data send_buffer_from_queue={123,"hello\n"};
struct Queue_data read_buffer_from_queue;
key_t key;
int msgID;
void send_msg_to_queue()//子进程发送消息
{
//定义结构体用于从消息队列读数据
  
  int send_flag;
  key = ftok(".",'z');//生成键值
  msgID = msgget(key,IPC_CREAT|0777);//参数1为消息队列的标识符;返回值为-1指失败,否则为队列的ID

  if(msgID==-1)
  {
    printf("open queue failed\r\n");
  }
  else
  {
    printf("childProcess open queue success,msgID=%x\r\n",msgID);
    send_flag = msgsnd(msgID,&send_buffer_from_queue,strlen(send_buffer_from_queue.Queue_buff),0);
    if(send_flag == 0)
     {
        printf("send success\n");
     }
     else if(send_flag == -1)
     {
        printf("send failed\n");
      }
  }
}

void get_msg_from_queue()//父进程接收消息
{
    
    msgrcv(msgID,&read_buffer_from_queue,sizeof(read_buffer_from_queue),send_buffer_from_queue.type,0);
    printf("fatherProcess get from queue:%s\n",read_buffer_from_queue.Queue_buff);
}

///queue消息队列///

ipc.h

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>


#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct Queue_data{
        long type;
        char Queue_buff[128];
};

void my_pipe_for_creat_file();
void creat_file_child_process_notify_father_process();
void creat_file_father_process_read_notify_from_pipe();
void my_fifo_for_write_file();
void write_file_child_process_notify_father_process_by_fifo();
void send_msg_to_queue();
void get_msg_from_queue();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/589343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云原生-K8s-1】kubeadm搭建k8s集群(一主两从)完整教程及kubernetes简介

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录 Kubernetes简介1 kubernetes架构1.1m…

清凉一夏小风扇-React版

这里写目录标题 前言 一、效果二、代码分享三、总结 前言 本片文章主要是做一个小练习&#xff0c;通过react来制作一个风扇练习css动画。 vue3实现部分看这里–> 一、效果 二、代码分享 1、主体框架 “react”: “^18.2.0” “sass”: “^1.62.1” 2、主要技术点 使用事…

企业上云容灾如何实现碳中和?

随着能源成本的增加和数据消费的激增&#xff0c;“电耗”和“碳排放”成为今年世界移动通信大会热议的话题。目前&#xff0c;ICT行业耗电量约占全球用电量的7%。预计到2040年&#xff0c;ICT行业碳排放量占全球排放量的比例将上升至14%。 容灾是企业为了在灾难时保证业务继续…

基于html+css的图展示99

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

Log4j2 - JNDI 注入漏洞复现(CVE-2021-44228)

文章目录 Apache Log4j简介漏洞介绍影响版本漏洞编号影响组件应用 环境准备靶场搭建漏洞利用利用工具使用方式 反弹shell操作 漏洞修复建议 Apache Log4j简介 Apache log4j 是 Apache 的一个开源项目&#xff0c; Apache log4j2 是一个 Java 的日志记录工具。该工具重写了 log4…

03.hadoop上课笔记之hdfs环境的搭建和使用

1.启动网络 在windows任务管理器启动服务vm Dhcp #由动态ip变为静态 #启动网卡ifup ens33#修改网卡配置文件vi /etc/sysconfig/network-scripts/ifcfg-ens33BOOTSTRAPstaticIPADDR192.168.202.101NETMASK255.255.255.0GATEWAY192.168.202.2DNS1192.168.202.2#重启网络 servic…

Vue动态路由在实际项目中的应用(包含前后台细节)

背景 近期做一个公司的门户网站&#xff0c;在产品和新闻这一块需要用到动态路由。本节博客以产品板块为例说一下动态路由的应用。 另外如果路由相关的基础知识有问题&#xff0c;可以查看我的这篇博客&#xff1a; Vue2路由的详细讲解 另外&#xff0c;这篇博客也会涉及到一…

macOS visual studio code 没有读写权限 检查更新报错

问题描述 visual studio code 检查更新&#xff0c;报错&#xff0c;visual studio code没有磁盘读写权限。&#xff08;可能会导致插件安装报错&#xff1f;&#xff09; 报错&#xff1a;The application is on a read-only volume. Please move the application and try a…

网络安全人员需要考的几本(含金量高)的证书!

网络安全行业含金量最高的当属CISSP——注册信息系统安全专家。但这个认证也是大家公认比较难考的证书. 含金量次之的CISP——国家注册信息安全专业人员&#xff0c;包含CISE&#xff08;工程师&#xff09;、CISO&#xff08;管理&#xff09;、CISA&#xff08;外审&#xf…

面试前15天刷完这个笔记,拿下字节测开岗offer....

面试&#xff0c;跳槽&#xff0c;每天都在发生&#xff0c;跳槽&#xff0c;更是很常见的&#xff0c;对于每个人来说&#xff0c;跳槽的意义也各不相同&#xff0c;可能是一个人更向往一个更大的平台&#xff0c;更好的地方&#xff0c;可以通过换一个环境改变自己的现状。而…

基于OpenCV [c++]——形态学操作(分析和应用)

摘要&#xff1a; 形态学一般指生物学中研究动物和植物结构的一个分支。用数学形态学&#xff08;也称图像代数&#xff09;表示以形态为基础对图像进行分析的数学工具。 基本思想是用具有一定形态的结构元素去度量和提取图像中的对应形状以达到对图像分析和识别的目的。 形…

这篇文章把MOS管的基础知识讲透了

MOS管&#xff08;Metal-Oxide-Semiconductor field-effect transistor&#xff09;是一种常见的半导体器件&#xff0c;它在数字电路、模拟电路、功率电子等领域都有广泛的应用。本文将从MOS管的基本结构、工作原理、参数特性等方面讲解MOS管的基础知识。 一、MOS管的基本结构…

MediaPlayer error(-38, 0) 异常处理

文章目录 1、参考资料2、业务背景3、解决方案 1、参考资料 Media Player called in state 0, error (-38,0) MediaPlayer的使用 2、业务背景 对时长超过 5s 的音频提供裁剪、试听功能&#xff0c;裁剪、试听最大时长均为 5s。当视频长度在 5s ~ 6s 之间&#xff0c;试听暂停…

Flink on yarn任务日志怎么看

1、jobmanager日志 在yarn上可以直接看 2、taskmanager日志 在flink的webui中可以看&#xff0c;但是flink任务失败后&#xff0c;webui就不存在了&#xff0c;那怎么看&#xff1f; 这是jobmanager的地址 hadoop02:19888/jobhistory/logs/hadoop02:45454/container_e03_16844…

Apache应用和配置

目录 构建虚拟 Web 主机基于域名的虚拟主机基于IP地址的虚拟主机基于端口的虚拟主机 Apache 连接保持构建Web虚拟目录与用户授权限制Apache 日志分割 构建虚拟 Web 主机 虚拟Web主机指的是在同一台服务器中运行多个Web站点&#xff0c;其中每一个站点实际上并不独立占用整个服务…

【发电机、输变电JDL-5400A 电流继电器 报警信号切除故障JOSEF约瑟】

名称&#xff1a;电流继电器&#xff1b;品牌&#xff1a;JOSEF约瑟&#xff1b;型号&#xff1a;JDL-5400A&#xff1b;触点容量&#xff1a;250V2A&#xff1b;返回时间&#xff1a;≤35ms&#xff1b;整定范围&#xff1a;0.03-19.9A&#xff1b;特点&#xff1a;返回系数高…

应用案例 | 升级OPC Classic到OPC UA,实现安全高效的数据通信

一 背景 OPC&#xff08;OLE for Process Control&#xff0c;用于过程控制的OLE&#xff09;是工业自动化领域中常见的通信协议。它提供了一种标准化的方式&#xff0c;使得不同厂商的设备和软件可互相通信和交换数据。OPC Classic是旧版OPC规范&#xff0c;通过使用COM&…

LabVIEWCompactRIO 开发指南第六章42

LabVIEWCompactRIO 开发指南第六章42 要使用用户控制的I/O示例方法进行编程&#xff0c;请按照以下步骤操作&#xff0c;这些步骤引用了图6.9中的示例程序。 初始化进程 1.调用重置I/O函数。此调用完成后&#xff0c;模块已准备好使用用户控制的I/O采样函数执行采集。必须首…

财务共享五大价值助力央企构建世界一流财务管理体系

如果说小微企业是我国市场经济的毛细血管的话&#xff0c;那么央企就是承载着我国市场发展的主动脉。以规模为导向来看&#xff0c;央企完成了第一次长征&#xff0c;但央企在盈利能力、市场份额、行业地位、专利技术与优势、品牌影响力、市值管理、标准和规则制定话语权等软实…

从1万张模板中找的运营知识图谱,超级牛!

运营现在是时下大家都很熟悉的一个行业&#xff0c;我们熟知的有内容运营、用户运营、产品运营、新媒体运营、活动运营 社群运营、电商运营、品牌运营等多种运营方式。 想要做好运营&#xff0c;其实是需要很丰富的知识体系的&#xff0c;今天就给大家分享一些厉害的运营图谱。…