进程间通信小练习
[!info] 编写程序
创建两个进程:
父进程执行文件拷贝操作。如果接收到SIGUSR1信号,将打印出当前拷贝进度。
子进程每隔一个固定时间向父进程发生SIGUSR1信号。
vi src.txt
然后输几十个字
然后新建源程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/time.h>
#include <signal.h>
#define BUFSIZE 16// 文件拷贝状态
long total;
long current;void showProcess(int signo){printf("文件已拷贝: %2ld%%\n",current*100/total);
}void sendSIGUSR1(int signo){printf("向父进程发送信号\n");kill(getppid(),SIGUSR1);
}void copyFile(const char * srcfile,const char * dstfile){int sfd,dfd,pos;char buf[BUFSIZE];sfd = open(srcfile,O_RDONLY);if(sfd <0){perror("open()");exit(1);}// 获取文件大小struct stat st;if (stat(srcfile, &st) == 0) {total = st.st_size;printf("文件大小为:%ld 字节\n",total);} else {perror("stat()");}dfd = open(dstfile,O_WRONLY|O_CREAT|O_TRUNC,0644);if(dfd < 0 ){close(sfd);perror("open()");exit(1);}int len,ret;printf("开始拷贝\n");while (1){len = read(sfd,buf,BUFSIZE);if(len <0){perror("read()");break;}if(len == 0)break;// 缓冲区写出一次操作pos = 0; //pos指向缓冲区已写字符的末尾,len剩余字符个数while(len > 0){// ret 缓冲区已写入个数,write不一定写入指定的len长度,可能被其他事件打断返回写入的字符个数,// 这时候 pos偏移到pos+ret,len要变成len-ret,然后等待下次循环执行ret = write(dfd,buf+pos,len); current+=ret; // 已拷贝++if(ret < 0){perror("write()");exit(1);}pos+=ret;len-=ret;}// 减缓sleep(1);}close(dfd);close(sfd);
}int main(int argc,char **argv){if(argc<3){fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);exit(1);}pid_t pid = fork(); if(pid>0){signal(SIGUSR1,showProcess); // 注册SIGUSR1信号的捕捉处理函数copyFile(argv[1],argv[2]);//复制完kill子进程printf("拷贝完成\n");printf("杀死儿子\n");kill(pid,SIGKILL);printf("父亲 go die\n");}else if(pid==0){// 子程序定时发送信号signal(SIGALRM,sendSIGUSR1); // 注册SIGALRM信号的捕捉处理函数// 定时,周期1秒struct itimerval newtime;newtime.it_value.tv_sec = 1;newtime.it_value.tv_usec = 0; newtime.it_interval.tv_sec = 1;newtime.it_interval.tv_usec = 0;if(setitimer(ITIMER_REAL,&newtime,nullptr)==-1){perror("setitimer error");return -1;}while (1) {pause(); // 等待信号}}else{perror("fork()");exit(1);}return 0;
}
运行