进程中的fork与exec

一、fork()函数(父进程创建子进程)

一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
    一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

1、父进程复制出子进程中,父进程返回值为子进程的pid;

2、父进程复制出子进程中,子进程返回值为0;

3、父进程复制出子进程中,如果出现错误,fork返回一个负值;

我们用代码来模拟一下这个过程:

#include
#include
#include
#include
#include

int main(int argc,char* argv[],char* envp[])
{
   int i = 0;
   for(;i < 2;i++)
   {
    pid_t pid = fork();
    printf("A");
   
   }
   exit(0);
}

fork()函数的特点:

1)fork函数在复制时,会将父进程的文件描述符全部都复制过去;

2)fork函数在复制时,若父进程有锁,则两个进程不会共用一把锁,但是子进程会复制过去父进程锁的状态;

3)fork函数在复制时,会将父进程的缓冲区的内容也复制,如上方代码执行后会打印出8个A;

二、exec()函数(替换进程函数)

       fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。

1)所需头文件:

#include

2)函数原型:

int execl(const char *pathname, const char *arg, ...)

int execv(const char *pathname, char *const argv[])

int execle(const char *pathname, const char *arg, ..., char *const envp[])

int execve(const char *pathname, char *const argv[], char *const envp[])

int execlp(const char *filename, const char *arg, ...)

int execvp(const char *filename, char *const argv[])

函数返回值:

成功:函数不会返回

出错:返回-1,失败原因记录在error中

同样使用代码:

#include
#include
#include
#include
#include

int main(int argc,char* argv[],char*envp[])
{
    printf("exec pid = %d\n",getpid());

    pid_t pid = fork();
    assert(pid != -1);
/*
    if(pid == 0)
    {
        char* myargv[] = {"b","hello","abc","123",(char*)0};
        char* myenvp[] = {"MYSTR=hello",,"VAL=100",(char*)0};
     // execl("./b","b","hello","abc","123",(char*)0);
        execve("./b",myargv,myenvp);
        perror("execl error");
    }
    */
/*
    if(pid == 0)
    {
        execl("/bin/ps","-f",(char*)0);
        perror("execl error");
        exit(0);
    }

    wait(NULL);
    printf("main error\n");
*/
    
   // execl("/bin/ps","ps","-ef",(char*)0);

    execlp("ps","ps","-f",(char*)0);
   
   // execlp("/bin/ps","ps","-f",(char*)0,envp);
   
  //  char* myargv[] = {"ps","-f",(char*)0};
  
   // execv("/bin/ps",myargv);
  
   // execvp("ps",myargv);
   
    execve("/bin/ps",myargv,envp);

    if(errno = ENOENT)
    {
        perror("execl error");
    }
    
    /*
    char * ls_argv[] = {"main", "-a", NULL};
    if(fork() == 0)
    {
       // if(execv("/bin/ls", ls_argv) < 0)
        if(execv("/home/ws/cy1706/jiaobeng/main", ls_argv) < 0)
        {
            perror("execl error");
        }
    }
    */
   exit(0);
}

 代码中将子进程替换成一些ls或ps系统命令。

你可能感兴趣的:(Linux,C语言)