• 进程


    pid & ppid

    通过getpid()可以获取进程ID(PID),getppid()可以获取父进程ID(PPID)。

    SYNOPSIS

    #include <sys/types.h>
    #include <unistd.h>
    
    pid_t getpid(void);
    pid_t getppid(void);

    进程控制编程

    fork()

    fork函数用于从已存在进程(父进程)中创建一个新进程(子进程)。

    父进程的返回值是子进程的进程号,而子进程则返回0。因此,可以通过返回值来判定该进程是父进程还是子进程。

    使用fork函数得到的子进程是父进程的一个复制品,所以效率很低。
    SYNOPSIS

    #include <unistd.h>
    
    pid_t fork(void);

    实例:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main()
    {
      pid_t result = fork();
      if(result <= -1){
      perror("fork");
      exit;
    }
    else if(result == 0){
      printf("child id is %d, parent id is %d
    ", getpid(), getppid());
    }
    else{
      printf("parent id is %d
    ", getpid());
    }
    
    return 0;
    }

    运行结果:

    xxx@xxx-pc:~/Documents$ ./a.out 
    parent id is 5888
    child id is 5889, parent id is 5888

    exec函数族

    exec 函数族就提供了一个在进程中启动另一个程序执行的方法。

    exec 函数族成员函数语法

    所需头文件

    #include <unistd.h>

    函数原型 int execl(const char *path, const char *arg, ...)
    int execv(const char *path, char *const argv[])
    int execle(const char *path, const char *arg, ..., char *const envp[])
    int execve(const char *path, char *const argv[], char *const envp[])
    int execlp(const char *file, const char *arg, ...)
    int execvp(const char *file, char *const argv[])
    函数返回值

    −1:出错

     
     
     
     
     
     
     
     
     
     
     
     
     
    exec 函数族成员函数语法

    前 4 位

    统一为:exec

    第 5 位 l:参数传递为逐个列举方式 execl、execle、execlp v:参数传递为构造指针数组方式 execv、execve、execvp
    第 6 位

    e:可传递新进程环境变量 execle、execve p:可执行文件查找方式为文件名 execlp、execvp

     

    实例1:

    int main()
    {
        if(fork()==0){
        /*调用 execlp 函数,这里相当于调用了“ps -ef”命令*/
        if(execlp("ps","ps","-ef",NULL)<0)
            perror("execlp error!");
        }
    }

    实例2:

    int main()
    {
        if(fork()==0){
        /*调用 execl 函数,注意这里要给出 ps 程序所在的完整路径*/
        if(execl("/bin/ps","ps","-ef",NULL)<0)
            perror("execl error!");
        }
    }    

    实例3:

    int main()
    {
        /*命令参数列表,必须以 NULL 结尾*/
        char *envp[]={"PATH=/tmp","USER=sunq",NULL};
        if(fork()==0){
        /*调用 execle 函数,注意这里也要指出 env 的完整路径*/
        if(execle("/usr/bin/env","env",NULL,envp)<0)
            perror("execle error!");
        }
    }    

    实例4:

    int main()
    {
        /*命令参数列表,必须以 NULL 结尾*/
        char *arg[]={"env",NULL};
        char *envp[]={"PATH=/tmp","USER=sunq",NULL};
        if(fork()==0){
        if(execve("/usr/bin/env",arg,envp)<0)
            perror("execve error!");
        }
    }

    实例3和4的结果:

    xxx@xxx-pc:~/Documents$ ./a.out 
    PATH=/tmp
    USER=sunq

    envp修改的是当前进程的环境变量。

    exec 函数族使用注意点:

    在使用 exec 函数族时,一定要加上错误判断语句。因为 exec 很容易执行失败,其中最常见的原因有:
    • 找不到文件或路径,此时 errno 被设置为 ENOENT;
    • 数组 argv 和 envp 忘记用 NULL 结束,此时 errno 被设置为 EFAULT;
    • 没有对应可执行文件的运行权限,此时 errno 被设置为 EACCES。

    exit 和_exit

    exit()函数与_exit()函数最大的区别就在于 exit()函数在调用 exit 系统之前要检查文件的打开情况,把文件缓冲区中的内容写回文件。

    SYNOPSIS

    #include <unistd.h>
    
    void _exit(int status);

    实例exit():

    int main()
    {
        printf("Using exit...
    ");
        printf("This is the content in buffer");
        exit(0);
    }

    结果:

    Using exit...
    This is the content in buffer

    实例_exit():

    int main()
    {
        printf("Using exit...
    ");
        printf("This is the content in buffer");
        _exit(0);
    }

    结果:

    Using exit...

    wait 和 waitpid

    wait 函数和 是用于使父进程(也就是调用 wait 的进程)阻塞,直到一个子进程结束或者该进程接到了一个指定的信号为止。

    waitpid 函数功能更强大,还可以实现非阻塞版本。

    实际上 wait 函数只是 waitpid 函数的一个特例,在 Linux 内部实现 wait 函数时直接调用的就是 waitpid 函数。 

    SYNOPSIS

    #include <sys/types.h>
    #include <sys/wait.h>
    
    pid_t wait(int *status);
    
    pid_t waitpid(pid_t pid, int *status, int options);

    实例1:

    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
        pid_t pc,pr;
        pc=fork();
        if(pc<0)
            printf("Error fork.
    ");
        else if(pc==0){
            sleep(5);
            exit(0);
        }
        else{
            do{
                /* father process, so pc value is child id */
                pr=waitpid(pc,NULL,WNOHANG);
                if(pr==0){
                    printf("The child process has not exited
    ");
                    sleep(1);
                }
            }while(pr==0);
        if(pr==pc)
            printf("Get child %d
    ",pr);
        else
            printf("some error occured.
    ");
        }
    }

    结果如下:

    waitpid(pc,NULL,WNOHANG) 提供了非阻塞版本。

    xxx@xxx-pc:~/Documents$ ./a.out 
    The child process has not exited
    The child process has not exited
    The child process has not exited
    The child process has not exited
    The child process has not exited
    Get child 3366

    如果换成waitpid(pc,NULL,0)或wait(NULL)则是阻塞版本。

    结果如下:

    xxx@xxx-pc:~/Documents$ ./a.out 
    Get child 3440

    多进程实例

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>
    
    int main(void)
    {
        pid_t child1,child2,child;
    
        child1 = fork();
        child2 = fork();
        
        if(child1 == -1){
            perror("child1 fork");
            exit(1);
        }else if(child1 == 0){
            printf("In child1: execute 'ls -l'
    ");
            if(execlp("ls","ls","-l",NULL)<0)
                perror("child1 execlp");
        }
    
        if(child2 == -1){
            perror("child2 fork");
            exit(1);
        }else if(child2 == 0){
            printf("In child2: sleep for 5 seconds and then exit
    ");
            sleep(5);
            exit(0);
        }else{
            printf("In father process:
    ");
            do{
                child = waitpid(child2, NULL, WNOHANG);
                if(child == 0){
                    printf("The child2 process has not exited!
    ");
                    sleep(1);
                }
            }while(child == 0);
            if(child == child2)
                printf("Get child2
    ");
            else
                printf("Error occured!
    ");
        }
    }

    运行结果:

    多运行几次,结果可能会不太一样。因为,子进程之间存在着竞争关系。

    xxx@xxx-pc:~/Documents$ ./a.out 
    In father process:
    The child2 process has not exited!
    In child2: sleep for 5 seconds and then exit
    In child1: execute 'ls -l'
    In child1: execute 'ls -l'
    total 36
    total 36
    -rwxrwxr-x 1 xxx xxx 8824 Apr 27 00:12 a.out
    -rwxrwxr-x 1 xxx xxx 8824 Apr 27 00:12 a.out
    -rw-rw-r-- 1 xxx xxx    6 Apr 23 16:49 markd.md
    -rw-rw-r-- 1 xxx xxx  835 Apr 27 00:12 p2.c
    -rw-rw-r-- 1 xxx xxx  837 Apr 27 00:11 p2.c~
    -rw-rw-r-- 1 xxx xxx    6 Apr 23 16:49 markd.md
    -rw-rw-r-- 1 xxx xxx  892 Apr 26 23:31 pid.c
    -rw-rw-r-- 1 xxx xxx  865 Apr 26 23:30 pid.c~
    -rw-rw-r-- 1 xxx xxx  835 Apr 27 00:12 p2.c
    -rw-rw-r-- 1 xxx xxx  156 Apr 23 16:48 piddump.c
    -rw-rw-r-- 1 xxx xxx  837 Apr 27 00:11 p2.c~
    -rw-rw-r-- 1 xxx xxx  892 Apr 26 23:31 pid.c
    -rw-rw-r-- 1 xxx xxx  865 Apr 26 23:30 pid.c~
    -rw-rw-r-- 1 xxx xxx  156 Apr 23 16:48 piddump.c
    The child2 process has not exited!
    The child2 process has not exited!
    The child2 process has not exited!
    The child2 process has not exited!
    Get child2
  • 相关阅读:
    ajax请求发送json数据
    jQuery与Prototype冲突解决办法
    cookie设置HttpOnly、Secure属性
    web.config,system.web中加<machineKey
    登陆页面粒子效果
    cmd命令登陆oracle
    oracle 千万级数据表增加索引
    springboot报错:expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    数据库备份
    unixbench性能测试跑分工具
  • 原文地址:https://www.cnblogs.com/fuluwwa/p/6753270.html
Copyright © 2020-2023  润新知