sigset_t wait_set; sigset_t zero_set; int sig_no; struct sigaction act; const struct timespec tv = {5,0}; //timeout
siginfo_t sig_info ;//传递的信息结构
void sig_pipe(int signo) { printf("in sig_pipe () , signo=%d\n",signo); printf("errno=%d\n",errno); printf("access_mode = %d\n",access_mode); //if(errno == EPIPE && access_mode == ACCESS_WRITE ) { //仅对write archive的时候有效
if(access_mode == ACCESS_WRITE ) { //当no space left的时候,为什么errno=0 ???
printf("in catch function , ENOSPC \n"); RetCode = -TAR_NO_SPACE_LEFT; } }
void sighandler_sigchld(int signo) { int child_count; pid_t pid; int status; printf("recieved signo = %d\n",signo); if(signo == SIGCHLD) { /* Reap defunct children until there aren't any more. */ for(;;) { pid = waitpid((pid_t) - 1, &status, WNOHANG); //WNOHANG 防止阻塞
jprintf("\n\n++++++ waitpid retunr pid (%d) , status (%d) \n",pid,status); if ((int) pid == 0) /* none left */ break; if ((int) pid < 0) { if (errno == EINTR) /* because of ptrace */ continue; /* ECHILD shouldn't happen with the WNOHANG option, but with ** some kernels it does anyway. Ignore it. */ //其他的情况,就说明没有子进程需要回收了, 可以跳出循环
break; } } } }
void wait_Zombie(void) { int child_count; pid_t pid; int status; /* Reap defunct children until there aren't any more. */ for(;;) { pid = waitpid((pid_t) - 1, &status, WNOHANG); //WNOHANG 防止阻塞
jprintf("========= in uncompress parent process free Zombie \n" "waitpid retunr pid (%d) , status (%d) \n",pid,status); if ((int) pid == 0) /* none left */ break; if ((int) pid < 0) { if (errno == EINTR) /* because of ptrace */ continue; /* ECHILD shouldn't happen with the WNOHANG option, but with ** some kernels it does anyway. Ignore it. */ //其他的情况,就说明没有子进程需要回收了, 可以跳出循环
break; } } }
/*=================================================== 创建.tar.gz 文件 这个compress 比 uncompress可简单多了。 this function will return pipe[write] id , then write block into this archive =================================================== */ int sys_child_open_for_compress_xx (const char *archive_file_path) {
int parent_pipe[2]; int child_pipe[2]; pid_t grandchild_pid; pid_t child_pid; int wait_status;
//siginfo_t sig_info ;//传递的信息结构
sigemptyset(&zero_set); sigemptyset(&wait_set); sigaddset(&wait_set,SIGUSR1);
sigprocmask(SIG_SETMASK,&zero_set,NULL);
act.sa_handler = sighandler_usr1; //act.sa_handler = SIG_DFL;
sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; //这个很关键,否则无法用sigqueue() 发送信号
sigaction(SIGUSR1,&act,NULL);
xpipe (parent_pipe); child_pid = xfork ();
// -------------------------------- parent progress ---------------------------------
if (child_pid > 0) { /* The parent tar is still here! Just clean up. */ printf("\n\n--------- in compress : child_pid= %d\n",child_pid); archive = parent_pipe[PWRITE]; xclose (parent_pipe[PREAD]);
//在这里等待子进程的返回值,来确定是否有必要继续运行下去
again: sigprocmask(SIG_BLOCK,&wait_set,NULL); sig_no = sigtimedwait(&wait_set,&sig_info,&tv); //父进程会一直阻塞tv时间,然后就返回
printf("sig_no=%d\n",sig_no); if(sig_no == -1) { //可能超时,也可能是被别的信号中断,在下面判
printf("sigtimedwait return exception , sig_no = -1\n"); if(errno == EINTR)//interrupted by others signals
{ jprintf("parent process has been interrupted by others signal \n"); jprintf("it will continue to be blocked \n"); goto again; } else if(errno == EAGAIN)//resource unavilable , timeout
; //jump out; do nothing
return -TAR_CANNOT_CREATE_ARCHIVE_FILE; } else { printf("child process return value = %d\n",sig_info.si_int); if(sig_info.si_int > 0) { //信号传递的信息:传递的子进程create的archive的fd
printf("ok\n"); printf("child process create fd=%d\n",sig_info.si_int);
return archive; } else { // fd <=0
printf("can't create archive file ,please check directory\n"); return -TAR_CANNOT_CREATE_ARCHIVE_FILE;
//FIXME: 我的意思是子进程无法创建archive , 的时候, 返回负数, 但是archive本身永远是对的
//不过不是大问题,最多没有close(archive)而已。
}
}
//-------------------------------------------------------------------
//return archive; 原来是直接返回,这是不对的,必须经过上面的判断才可
} else if (child_pid == 0) {
/* The new born child tar is here! */ union sigval rc_val; //program_name = _("tar (child)");
xdup2 (parent_pipe[PREAD], STDIN_FILENO);//dup2 to stdin
xclose (parent_pipe[PWRITE]);
// if (!_remdev (archive_name_array[0])
// && is_regular_file (archive_name_array[0]))
{
int _tar_gz_fd = 0; pid_t p_pid = 0; /* We don't need a grandchild tar. Open the archive and launch the compressor. */ if (strcmp (archive_file_path, "-")) //最一般的情况,比如 tar zcvf bob.tar.gz system.c update.c
{
_tar_gz_fd = creat (archive_file_path, MODE_RW); jprintf("in child progress (gzip) ,fd = %d\n",_tar_gz_fd);
rc_val.sival_int = _tar_gz_fd; //传递整型值
//这里要通知父进程
p_pid = getppid(); if(p_pid !=1) { //如果父进程是1(init) , 就不要发信号(事实上没有这种可能,因为父进程已经阻塞了)
jprintf("has send SIGUSR1 signal \n"); sleep(1); //in Marvell 的扳子上,子进程run的太快了,以至于父进程还没有执行到sigtimedwait()函数
//因此必须sleep一下, 确保父进程已经blocked
sigqueue(p_pid,SIGUSR1,rc_val); //kill的更强的用法,除了kill的功能外,还可以传递整形值和指针
//exit(0); //
}
if (_tar_gz_fd < 0) { int saved_errno = errno;
errno = saved_errno; // open_fatal (archive_file_path);
exit(0); }
xdup2 (_tar_gz_fd, STDOUT_FILENO); //父进程会把tar的结果输出到 archive中去, gzip到这里取结果!
}
execlp (use_compress_program_option, use_compress_program_option, NULL); //如果gzip执行正常,就不会执行到下面的代码
jprintf("gzip run status = %d\n",errno); //exec_fatal (use_compress_program_option);
}
}
}
|