zoukankan      html  css  js  c++  java
  • 进程控制(二)

    5 wait和waitpid函数

      当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。

    5.1调用wait或waitpid的进程可能会:

        阻塞(如果其子进程都还在运行)

        带子进程的终止状态立即返回

        出错立即返回

    5.2wait和waitpid的区别: 

        在一个子进程终止前, wait 使其调用者阻塞,而 waitpid 有一选择项,可使调用者不阻塞。

        waitpid并不等待第一个终止的子进程—它有若干个选择项,可以控制它所等待的进程。

    代码示例:

    #include "ourhdr.h"
    #include <sys/wait.h>
    
    void pr_exit(int status)
    {
    	if (WIFEXITED(status))
    		printf("normal termination, exit status = %d
    ",
    				WEXITSTATUS(status));
    	else if (WIFSIGNALED(status))
    		printf("abnormal termination, signal number = %d%s
    ",
    				WTERMSIG(status),
    #ifdef	WCOREDUMP
    				WCOREDUMP(status) ? " (core file generated)" : "");
    #else
    				"");
    #endif
    	else if (WIFSTOPPED(status))
    		printf("child stopped, signal number = %d
    ",
    				WSTOPSIG(status));
    }
    
    int main(void)
    {
    	pid_t	pid;
    	int		status;
    
    	if ((pid = fork()) < 0)
    		err_sys("fork error");
    	else if (pid == 0)				/* child */
    		exit(7);
    
    	if (wait(&status) != pid)		/* wait for child */
    		err_sys("wait error");
    	pr_exit(status);				/* and print its status */
    
    	if ((pid = fork()) < 0)
    		err_sys("fork error");
    	else if (pid == 0)				/* child */
    		abort();					/* generates SIGABRT */
    
    	if (wait(&status) != pid)		/* wait for child */
    		err_sys("wait error");
    	pr_exit(status);				/* and print its status */
    
    	if ((pid = fork()) < 0)
    		err_sys("fork error");
    	else if (pid == 0)				/* child */
    		status /= 0;				/* divide by 0 generates SIGFPE */
    
    	if (wait(&status) != pid)		/* wait for child */
    		err_sys("wait error");
    	pr_exit(status);				/* and print its status */
    
    	exit(0);
    }
    

      打印结果:

    [root@rac1 fork]# gcc wait.c 
    wait.c: In function ‘main’:
    wait.c:48: warning: division by zero
    
    [root@rac1 fork]# ./a.out 
    normal termination, exit status = 7
    abnormal termination, signal number = 6
    abnormal termination, signal number = 8
    

     5.3如果一个进程要 f o r k一个子进程,但不要求它等待子进程终止,也不希望子进程处于僵死状态直到父进程终止,实现这一要求的诀窍是调用 f o r k两次。

    代码示例:

    #include "ourhdr.h"
    #include <sys/wait.h>
    #include <sys/types.h>
    
    int
    main(void)
    {
    	pid_t	pid;
    
    	if ((pid = fork()) < 0) {
    		err_sys("fork error");
    	} else if (pid == 0) {		/* first child */
    		if ((pid = fork()) < 0)
    			err_sys("fork error");
    		else if (pid > 0)
    			exit(0);	/* parent from second fork == first child */
    
    		/*
    		 * We're the second child; our parent becomes init as soon
    		 * as our real parent calls exit() in the statement above.
    		 * Here's where we'd continue executing, knowing that when
    		 * we're done, init will reap our status.
    		 */
    		sleep(2);
    		printf("second child, parent pid = %d
    ", getppid());
    		exit(0);
    	}
    
    	if (waitpid(pid, NULL, 0) != pid)	/* wait for first child */
    		err_sys("waitpid error");
    
    	/*
    	 * We're the parent (the original process); we continue executing,
    	 * knowing that we're not the parent of the second child.
    	 */
    	exit(0);
    }

      

     打印结果:

    [root@rac1 fork]# ./a.out 
    [root@rac1 fork]# second child, parent pid = 1
    

      

    6 wait3 和wait4函数

    7 竞态条件

      当多个进程都企图对共享数据进行某种处理,而最后的结果又取决于进程运行的顺序时,则我们认为这发生了竞态条件

      在父、子进程的关系中,常常出现下述情况。在 f o r k之后,父、子进程都有一些事情要做。例如,父进程可能以子进程 I D更新日志文件中的一个记录,而子进程则可能要为父进程创建一个文件

     代码示例:

    tellwait.h

    #include <sys/types.h>
    static int	pfd1[2], pfd2[2];
    
    void TELL_WAIT(void)
    {
    	if (pipe(pfd1) < 0 || pipe(pfd2) < 0)
    		err_sys("pipe error");
    }
    
    void TELL_PARENT (pid_t pid)
    {
    	if (write(pfd2[1], "c", 1) != 1)
    		err_sys("write error");
    }
    
    void WAIT_PARENT(void)
    {
    	char	c;
    
    	if (read(pfd1[0], &c, 1) != 1)
    		err_sys("read error");
    
    	if (c != 'p')
    		err_quit("WAIT_PARENT: incorrect data");
    }
    
    void TELL_CHILD(pid_t pid)
    {
    	if (write(pfd1[1], "p", 1) != 1)
    		err_sys("write error");
    }
    
    void WAIT_CHILD(void)
    {
    	char	c;
    
    	if (read(pfd2[0], &c, 1) != 1)
    		err_sys("read error");
    
    	if (c != 'c')
    		err_quit("WAIT_CHILD: incorrect data");
    }
    

      tell.c

    #include "ourhdr.h"
    
    static void charatatime(char *);
    
    int main(void)
    {
    	pid_t	pid;
    
    	TELL_WAIT();
    
    	if ((pid = fork()) < 0) {
    		err_sys("fork error");
    	} else if (pid == 0) {
    		WAIT_PARENT();		/* parent goes first */
    		charatatime("output from child
    ");
    	} else {
    		charatatime("output from parent
    ");
    		TELL_CHILD(pid);
    	}
    	exit(0);
    }
    
    static void
    charatatime(char *str)
    {
    	char	*ptr;
    	int		c;
    
    	setbuf(stdout, NULL);			/* set unbuffered */
    	for (ptr = str; (c = *ptr++) != 0; )
    		putc(c, stdout);
    }
    

      运行结果:

    [root@rac1 fork]# ./tell 
    output from parent
    [root@rac1 fork]# output from child
    
    [root@rac1 fork]# 
    

      

     8 exec函数

        用f o r k函数创建子进程后,子进程往往要调用一种 e x e c函数以执行另一个程序。
        当进程调用一种 e x e c函数时,该进程完全由新程序代换,而新程序则从其 m a i n函数开始执行

    #include <unistd.h>
    int execl(const char * pathname, const char * arg0, ... /* (char *) 0 */);
    int execv(const char * pathname, char *const  argv  [] );
    int execle(const char * pathname, const char * arg0, .../* (char *)0, char *const  envp [] */);
    int execve(const char * pathname, char *const  argv  [], char *const  envp  [] );
    int execlp(const char * filename, const char * arg0, ... /* (char *) 0 */);
    int execvp(const char * filename, char *const  argv  [] );
    六个函数返回:若出错则为- 1,若成功则不返回
    

      

    代码示例:

    #include "ourhdr.h"
    #include <sys/wait.h>
    
    char	*env_init[] = { "USER=unknown", "PATH=/tmp", NULL };
    
    int
    main(void)
    {
    	pid_t	pid;
    
    	if ((pid = fork()) < 0) {
    		err_sys("fork error");
    	} else if (pid == 0) {	/* specify pathname, specify environment */
    		if (execle("/usr/local/bin/python", "python", "myarg1",
    				"--", (char *)0, env_init) < 0)
    			err_sys("execle error");
    	}
    
    	if (waitpid(pid, NULL, 0) < 0)
    		err_sys("wait error");
    
    	if ((pid = fork()) < 0) {
    		err_sys("fork error");
    	} else if (pid == 0) {	/* specify filename, inherit environment */
    		if (execlp("python", "", "myarg2", (char *)0) < 0)
    			err_sys("execlp error");
    	}
    
    	exit(0);
    }
    

      

  • 相关阅读:
    【转】IntelliJ IDEA2017.3激活
    【转】构建Maven项目自动下载jar包
    【转】Intellij idea 的maven项目如何通过maven自动下载jar包
    【转】在IDEA中创建maven项目
    【转】maven的安装、配置以及下载jar包
    【转】git修改文件后,提交到远程仓库
    基于MbedTLS的AES加密实现,含STM32H7和STM32F4的实现例程
    Cortex-M7,A8,A9,A15与ADI的BlackFin以及SHARC的DSP性能PK
    基于V6的中移动物联测试例子,当前测试还挺稳定
    中移动物联手机端APP软件
  • 原文地址:https://www.cnblogs.com/huanhuanang/p/4440660.html
Copyright © 2011-2022 走看看