【APUE】进程控制

 

  • 进程标识符
每个进程都有一个非负整数表示其唯一的id
id=0的进程,调度进程,也叫交换进程,不执行磁盘上的程序,系统进程,内核的一部分。
id=1为init进程,自举过程结束后由内核调用,读与系统有关的初始化文件。
getpid() 进程id
getppid() 父进程id
getuid()  实际用户id
geteuid()  有效用户id
getgid() 组id
getegid() 有效组id
 
 
 
  • fork函数
fork()创建一个新的进程,子进程中返回0,父进程中返回子进程id 出错返回-1
被调用一次但是返回两次
 
子进程是父进程的副本,获得父进程的数据空间,堆和栈的副本,仅仅是副本但是不共享。父子进程共享正文段。
由于fork之后经常跟随者exec,所以现在很多实现并不执行一个父进程数据段,堆和栈的完全复制,而是使用了写时复制技术,如果需要修改,就复制内存作为一个副本。
 
#include"apue.h"

int glob = 6;
char buf[] = "a write to std out\n";

int main(void)
{
    int var;
    int pid;

    var = 88;

/*    if(write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
    {
        printf("error\n");
        exit(0);
    }
*/
    printf("before fork\n");  \\有没有\n会导致显示结果的区别

    if((pid = fork())<0)
    {
        printf("error\n");
        exit(0);
    }
    else if(pid == 0)
    {
        glob++;
        var++;
    }
    else
    {
        sleep(2);
    }
    printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
    exit(0);
}

 

一般来说fork之后先执行子进程还是先执行父进程是不确定的。
输出时候的缓冲类型会导致输出结果的不同。因为子进程也复制了父进程的缓冲区。
 
 
 
  • 文件共享
在重定向父进程的标准输出时,子进程的标准输出也被重定向。fork的一个特性是父进程的所有打开文件描述符都被复制到子进程中。父子进程的每个相同的文件描述符共享一个文件表项。
 
因此常用的处理方式是
1)父进程等待子进程的完成,这种情况下,父进程无需对其描述符做任何处理。当子进程终止后,他已经将共享的描述符进行了处理。
2)父子进程执行不同的程序段,各自关闭其不需要的描述符,网络通信中经常使用
 
fork的一般用法:
1)一个父进程希望复制自己,使父子进程同时执行不同的代码段,网络服务进程中很常见
2)一个进程需要执行一个不同的程序
 
 
 
 
  • wait和waitpid函数
当一个进程终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件,父进程可以选择忽略或者调用一个处理函数。
 
调用wait或者waitpid之后:
如果其所有子进程还在运行,则阻塞。
如果第一个子进程已经终止正在等待父进程获取其终止状态,则获取状态后返回。
如果没有任何子进程,则出错返回。
 
pid_t wait(int *statloc)
pid_t waitpid(pid_t pid, int *statloc, int options)
后者可以使调用者不阻塞,也可以控制等待其他进程,不局限于一个子进程。
 
exec函数
当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则是从其main函数开始执行。用一个全新的程序替换了当前的进程的正文、数据、堆和栈段。并不创建新的进程。
 
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 *pathname,  const char *arg0, /*(char *)0*/)
int execvp(const char *pathname, char *const argv[])
主要区别在于:
文件名和路径名
参数表的传递
是否可以传递环境变量
 
#include "apue.h"
#include <sys/wait.h>

char *env_init[] = {"USER=unknown", "PATH=/home/users/zhuhankun/apue_program", NULL};

int main()
{
    int pid;

    if((pid=fork()) < 0)
    {
        printf("fork error\n");
    }
    else if(pid == 0)
    {
        if(execle("/home/users/zhuhankun/apue_program/echoall.c", "echoall.c", "myarg1", "MY_ARG2", (char *)0, env_init))
        {
            printf("execle error\n");
            exit(-1);
        }
    }
    if(waitpid(pid, NULL, 0) < 0)
    {
        printf("wait error\n");
        exit(-1);
    }

    if((pid = fork())<0)
    {
        printf("fork 2 error\n");
    }
    else if(pid==0)
    {
        if(execlp("echoall.c", "echoall.c", "only 1 arg", (char *)0) < 0)
        {
            printf("execlp error\n");
                        exit(-1);
        }
    }
    exit(0);
}

 

 

 
  • system函数
在程序中实现一个命令字符串。
在其实现中调用了fork exec和waitpid,因此有三种返回值
 
#include"apue.h"
#include<sys/wait.h>
#include"pr_exit.h"

void pr_exit(int status)
{
    if (WIFEXITED(status))
        printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
    else if (WIFSIGNALED(status))
        printf("abnormal termination, signal number = %d %s\n", WTERMSIG(status),
                #ifdef WCOREDUMP
                WCOREDUMP(status)?"(core file generated)" : "");
        #else
            "");
        #endif
    else if(WIFSTOPPED(status))
        printf("child stopped, signal number = %d\n", WSTOPSIG(status));
}

 

 
#include<sys/wait.h>
#include"apue.h"
#include"pr_exit.h"

void pr_exit(int statue);

int main(void)
{
    int status;
    if((status = system("date"))<0)
    {
        printf("date error\n");
    }
    pr_exit(status);

    if((status = system("nosuchcommand"))<0)
    {
        printf("nosuchcommand error\n");
    }
    pr_exit(status);
    
    if((status = system("who; exit 44"))<0)
    {
        printf("who error\n");
    }
    pr_exit(status);

    exit(0);
}

 

 

posted @ 2012-09-19 13:13  w0w0  阅读(235)  评论(0编辑  收藏  举报