Linux c进程管理—创建进程 system、execl、execlp、fork

来源:互联网 发布:矩阵的协方差怎么求 编辑:程序博客网 时间:2024/05/24 03:22

Linux c 进程管理:

 

1.      创建进程:

       system函数:

        int system(const char*filename);

                                                 建立独立进程,拥有独立的代码空间,内存空间

                                                 等待新的进程执行完毕,system才返回.(阻塞)

         system:创建一个堵塞的新进程,新进程结束后,system才返回

 

         案例:

              使用system调用一个程序。

                    观察进程ID。

                    观察阻塞。

 

代码:

text.c

 

#include<stdio.h>

#include<unistd.h>

 

void  main()

{

      printf(“%d\n”,getpid());    //打印当前进程id

      sleep(10);               //进程睡眠10秒

}

 

gcctext.c –o text

 

system.c

 

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

 

void  main()

{

     printf(“%d\n”,getpid());

     int r=system(“./text”);

     printf(“%d\n”,r);

}

 

gccsystem.c –o main

 

结论:

     新进程的返回值与system返回值有关系。

        任何进程的返回值:不要超过255。一个字节。

        system的返回值中8-15位存放返回码(一个字节存放返回码)

     要想得到返回码,则不能直接用system的返回值,要取返回值的8-15位的内容。

     Linux提供一个宏来获取该值WEXITSTATUS(status)、包含在#include<sys/wait.h>中

 

代码:

 

text.c

 

#include<stdio.h>

#include<unistd.h>

 

int  main()

{

      printf(“%d\n”,getpid());    //打印当前进程id

      sleep(10);             //进程睡眠10秒

      return 99;

}

 

gcctext.c –o text

 

system.c

 

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

 

void  main()

{

     printf(“%d\n”,getpid());

     int r=system(“./text”);

     printf(“%d\n”,WEXITSTATUS(r));

}

 

gccsystem.c –o main

 

 

 

 

 

 

 

popen函数:

   #include<stdio.h>

   函数原型:

   FILE * popen ( constchar * command , const char * type );

int pclose ( FILE * stream );

 

popen:创建子进程

在父子进程之间建立一个管道

command: 是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用 -c 标志,shell将执行这个命令。

type: 只能是读或者写中的一种,得到的返回值(标准I/O 流)也具有和 type 相应的只读或只写类型。如果type 是 “r” 则文件指针连接到 command 的标准输出;如果 type 是 “w” 则文件指针连接到command 的标准输入。

返回值:

  如果调用成功,则返回一个读或者打开文件的指针,如果失败,返回NULL,具体错误要根据errno判断

  int pclose (FILE*stream)

  参数说明:

  stream:popen返回的文件指针

  返回值:

  如果调用失败,返回 -1

 

案例:

使用popen调用ls -l,并且建立一个管道读取输出

 

#include<stdio.h>

#include<unistd.h>

 

void main()

{

     char buf[1024];

     FILE *f=popen(“ls - l”,”r”);

     int fd=fileno(f);

     int r;

     while((r=read(fd,buf,1024))>0)

     {

            buf[r]=0;

          printf(“%s”,buf);

     }

     close(fd);

     pclose(f);

}

 

execlexecle:

          代替当前进程的代码空间中的代码数据,函数本身不创建新的进程。

 

excel函数:

int execl(const char * path,const char*arg,….);

第一个参数:替换的程序

第二个参数…..:命令行

                      命令行格式:命令名 选项参数

                      命令行结尾必须空字符串结尾

 

案例:

                     使用exec执行一个程序。

                     体会:*是否创建新的进程?没有

                              *体会execl的参数的命令行的格式

                              *体会execl与execlp的区别(execl只当前路径)(不是当前路径必须加绝对路径)

                                                               execlp使用系统的搜索路径

                               *体会execl替换当前进程的代码

 

代码:

 

text.c

 

#include<stdio.h>

#include<unistd.h>

 

void  main()

{

      printf(“%d\n”,getpid());    //打印当前进程id

      sleep(10);             //进程睡眠10秒

   

}

 

gcctext.c –o text

 

 

 

 

exec.c

 

#include<stdio.h>

#include<unistd.h>

 

 

void  main()

{

       printf(“main::%d\n”,getpid());

       int r=excel(“./text”,”text”,NULL);

       //int r=excel(“/bin/ls”,”ls”,”-l”,NULL);

       //int r=excelp(“ls”,”ls”,”-l”,NULL);

       printf(“结束:%d\n”,r);

}

 

总结:

程序运行后,两个打印进程id是一样,则excel和execlp不创建新的进程。

最后的打印结束的语句不能执行,因为excel和excelp是将新的程序的代码替换到该程序的代码空间中了。

两个函数的最后一个参数不许为0或NULL

函数的第一个参数是可执行程序的路径,第二个参数才是执行的命令

 

 

fork函数:

函数原型:

         pid_t  fork(); //1.创建进程

                     //2.新进程的代码是什么:克隆父进程的代码

                                                        而且克隆了执行的位置.(从父进程复制过来的代码,fork之前的代码不会再子进程中执行,子进程只会执行从父进程复制过来的fork以后的代码)

                     //3.在子进程不调用fork所以返回值=0;(pid=0为子进程的)

                                    //4.父子进程同时执行.

 

例子代码:

#include<stdio.h>

#include<unistd.h>

 

void  main()

{

      printf(“创建进程之前\n”);

      int pid=fork();

      printf(“创进程之后%d\n”,pid);

}

 

虽然子进程的代码是克隆父进程的,但我们也可以把子进程要执行的代码和父进程要执行的代码分开。

 

例子:

#include<stdio.h>

#include<unistd.h>

 

voidmain()

{

      printf(“创建进程之前:\n”);

      int pid=fork();

      if(pid==0)

      {

           printf(“子进程:\n”);

      }

      else

      {

           printf(“父进程:\n”);

      }

}