Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1638480
  • 博文数量: 197
  • 博客积分: 10046
  • 博客等级: 上将
  • 技术积分: 1983
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-07 12:36
个人简介

在外企做服务器开发, 目前是项目经理, 管理两个server开发的项目。不做嵌入式好久了。

文章分类
文章存档

2011年(2)

2010年(6)

2009年(18)

2008年(30)

2007年(100)

2006年(41)

分类: LINUX

2006-12-14 13:25:55

 
还是关于signal的高级用法:
 

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);


        }

    }

}

阅读(3251) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~