进程

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
原文地址:https://www.cnblogs.com/fuluwwa/p/6753270.html