一,功能描述
增加消息队列;使用自定义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();