第一篇只是简单使用了open,read,write,lseek实现了基本的记事本功能;
但是当前的系统是linux,应该发挥他的多进程,多线程的作用;
所以,本篇添加创建子进程和父进程等待子进程退出的功能。
有几个注意点:
wait()要与fork()配套出现,如果在使用fork()之前调用wait(),wait()的返回值则为-1,正常情况下wait()的返回值为子进程的PID.
参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就像下面这样:pid = wait(NULL);
如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。
WIFEXITED(status) 这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。
(请注意,虽然名字一样,这里的参数status并不同于wait唯一的参数–指向整数的指针status,而是那个指针所指向的整数,切记不要搞混了。)
WEXITSTATUS(status) 当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,WEXITSTATUS(status) 就会返回5;如果子进程调用exit(7),WEXITSTATUS(status)就会返回7。请注意,如果进程不是正常退出的,也就是说, WIFEXITED返回0,这个值就毫无意义。
代码:
main.c
#include "./io.h"struct CMD_input CMD_test1={"creat","copy","display","delete","write"};
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==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"
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;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;///} return 0;
}int task_sch()
{int return_of_fork;int status_childProcess;//子进程退出状态switch(flag_of_key_event){case Key_event_creatFile: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)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)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);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; default :break;}
}int creat_file()
{int ret=0;ret = creat(p->buffer_param2, S_IRWXU);//if(ret==-1){printf("creat file failed\r\n");}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 file1 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);exit(Key_event_writeFile);}}}
}int display_file()
{int fd=0;fd = system(path_of_file);//printf("fd = %d\r\n",fd);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_param3fdSRC = 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);exit(Key_event_copyFile);}}int delete_file()
{int fd=0;fd = system(path_of_file);//printf("fd = %d\r\n",fd);if(fd!=0){printf("deete file failed\r\n");}exit(Key_event_deleteFile);
}
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
struct CMD_input{char CMD_CREAT[10];char CMD_CP[10];char CMD_DISPLAY[10];char CMD_DELETA[10];char CMD_WRITE[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();
编译运行,如图父进程等待子进程退出后,打印出了子进程退出的状态;
如果子进程是被exit(2);退出的;
那么打印的printf("child process exit status:%d\n",WEXITSTATUS(status_childProcess));就是2.