exec()函数

1、exec()函数执行一个新的程序

exec()函数原型如下
int execl(cons char *pathname, const char *arg0,....);

int execle(const char *pathname, const char *arg0,..../*char *const envp[]*/);

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

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

int execlp(const char *filename,const char *arro,...);

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

"l"表示list,说明执行程序的命令行参数以列表的方式提供,并且以NULL结尾,但是没有参数个数限制。
"v"表示vector,说明命令行参数要以二维数组的形式提供给新程序,这个数组的每一行是一个命令参数。
"e"表示传递给新程序的环境变量,这个列表是一个二维数组,每一行是一个环境变量。如果没有显示地传递一个环境
表量表,那么新程序将复制父进程的环境表。
以p结尾的exec()函数表示第一个参数不是完整的路径名,而是一个程序名。

返回值:如果成功不返回任何值,如失败则返回-1。
例:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>

int main(void)
{
    pid_t pid;
    pid = fork();
    if(pid<0){
        printf("fail to fork\n");
        exit(0);
    }else if(pid == 0){
        if(execvp("./hello",NULL) < 0) {
            printf("fail to exec\n");
            printf("%s\n",strerror(errno));
            exit(errno);
         }
         printf("the child is not hello\n");
         exit(errno);
    }
    printf("the parent\n");
    return 0;
}

$ls
hell.c  hello  hello.c  test  test.c
$./test 
the parent
hello

执行了exec()函数的进程不改变以下进程特征
     1、进程ID和父进程ID
     2、实际用户ID和实际组ID
     3、进程组ID和附加组ID
     4、控制终端
     5、会话ID
     6、时钟余留时间
     7、当前工作目录和根目录。
     8、文件创建屏蔽字和文件锁
     9、信号屏蔽字和未处理信号集
    10、资源限制。

改变

      1、有效用户ID和有效组ID

2、在程序中执行shell命令

system()函数调用shell指令

#include<stdlib.h>
int system(const char * cmdstring)

参数cmdstring是需要执行的shell命令。
system的返回值的情况比较复杂,system()函数是一个库函数,其中封装了fork、exec和waitpid这个3个系统,

其返回值也要根据这3个系统调用的情况来讨论

    1、如果fork()函数和waitpid函数执行失败,则system()函数返回-1

    2、如果exec()函数执行失败,system()函数返回如图shell调用了exit(127)一样,表示指定文件不可执行

    3、如果3个函数都成功执行,system()函数返回执行程序的终止状态,其值和echo $?的值是一样的。

    4、如果参数cmdstring所指向的命令字符串为NULL,system()函数返回1。

例:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#define MAX 1024
int main(void)
{
      int fd,n;
      char buf[MAX];
      if(system("ls > temp.txt") == -1) {
             perror("fail to exec command\n");
             exit(0);
      }
      if(fd = open("temp.txt",O_RDWR) == -1) {
             perror("fail to open\n");
             exit(1);
      }
      if(fd = read(fd,buf,MAX) == -1){
             perror("fail to read\n");
             exit(1);
      }
      buf[n] = '\0';
      printf("%s",buf);
      return 0;
}

$gcc system.c -o system

$./system

temp.txt

system.c

system

3、等待进程退出操作
a、

wait()函数得到子进程的结束信息。

#include<sys/wait.h>

pid_t wait(int *statloc);

    调用wait()函数的进程会阻塞,直到该进程的任意一个子进程结束。wait()函数会取得结束的子进程的信息并返回子进程的进程ID,结束信息保存在参数statloc所指向的内存空间中,如果该进程没有子进程,则立即出错返回,返回值为-1.

状态                          判断宏                             取得宏
进程正常结束           WIFEXITED(status)           WEXITSTATUS(status)
进程异常结束           WIFSIGNALED(status)     WTERMSIG(status)
进程暂停                  WIFSTOPPED(status)      WSTOPSIG(status)

例:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main(void)
{
      pid_t pid;
      int num,status;
      pid = fork();
      if(pid<0){
           printf("fail to fork\n");
           exit(0);
      }else if(pid == 0) {
           printf("the fist, exit normally\n");
           exit(0);
      }else {
           if(wait(&status) == -1) {
                  perror("fail to wait");
                  exit(1);
           }
           if(WIFEXITED(status) == 1) {
                  printf("the status of first is :%d\n",WEXITSTATUS(status));
           }
      }
      pid = fork();
       if(pid<0) {
              printf("fail to fork\n");
              exit(0);
        }else if(pid == 0) {
              printf("the second, exit abnormally\n");
              num = 1/0;
        }else {
              if(wait(&status) == -1){
                     perror("fail to wait");
                     exit(1);
               }
              if(WIFEXITED(status) == 1) {
                     printf("the terminated signal is :%d\n",WEXITSTATUS(status));
              }
        }
        return 0;
}

$gcc wait.c -o wait
$./wait
the first ,exot normally
the stasus of first is:0
the second,exit abnormally
the terminated signal is:8

b、#include<sys/wait.h>

pid_t waitpid(pid_t pid, int *statloc,int options);

pid :指定要等待的子进程的进程ID,其还有一些其他作用,如
    -1 :     等待任意子进程
   >0:        等待进程ID和pid相等的子进程
   0:         等待组ID和pid相等的子进程 
   <-1:      等待组ID等于pid绝对值的组内的任意子进程。

option:
        WCONTINNUED :         当进程在暂停后继续执行,且其状态尚未报告,则返回其状态
        WNOHANG:                  当等待进程尚未结束运行时不阻塞,waitpid()函数直接返回
        WUNTRACED:             当子进程暂停,并且其状态自暂停以来还未报告过,则返回其状态
例:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main(void)
{
     pid_t pid;
     int num,status;
      pid = fork();
      if(pid<0) {
            printf("fail to fork\n");
            exit(1);
      }else if(pid == 0) {
            printf("the to fork\n");
           sleep(5);
           exit(0);
       }else {
           printf("the parent\n");
           if(waitpid(pid,NULL,WNOHANG) == 0) {
                printf("the child is not available now\n");
           }
      }
     printf("no waiting,parent done\n");
     return 0;
}

$gcc waitpid.c -o waitpid
./waitpid

the parent

the child is not available now
no waiting, parent done
the child

waitpid()函数和wait()函数的区别有以下3点:

     1、waitpid()函数可以指定一个子进程。

     2、waitpid()函数可以不阻塞等待一个子进程。

     3、waitpid()函数支持作业控制。

4、输出进程统计信息

#include<sys/types.h>
#include<sys/wait.h>
#include<sys/time.h>
#include<sys/source.h>
pid_t wait3(int *statlic, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *statloc, int options,struct rusage *rusage);







  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值