017 UNIX再学习 -- 函数 system

                                          
                                                                                   
                                                                                
                                           

一、system 函数


    
    
  1. #include <stdlib.h>
  2. int system(const char *command);

1、参数解析

command:shell 命令行字符串

2、函数解析

system 函数执行 command 参数表示的命令行,并返回命令进程的终止状态。若 command 参数是一个空指针 (NULL),则仅当命令处理程序可用时,system 返回非 0 值,这一特征可以确定在一个给定的操作系统上是否支持 system 函数。在 UNIX 中,system 总是可用的。

3、返回值

因为 system 在其实现中调用了 fork、exec 和 waitpid,因此有 3 种返回值。
(1)fork 失败或者 waitpid 返回除 EINTR 之外的出错,则 system 返回 -1,并且设置 errno
以指示错误类型。
(2)如果 exec 失败(表示不能执行 shell),则其返回值如同 shell 执行了 exit (127) 一样。
(3)否则所有 3 个函数(fork、exec 和 waitpid)都成功,那么 system 的返回值是 shell 的终止状态,其格式已在 waitpid 中说明。参看:UNIX再学习 -- exit 和 wait 系列函数

4、函数功能

主要用于执行指定的shell命令,以及shell脚本。shell 编程我们也讲了,参看:UNIX再学习 -- shell编程

5、示例说明


    
    
  1. //system函数的使用
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main(void)
  5. {
  6.   int status;
  7.   if ((status = system ( NULL)) == -1)
  8.   perror ( "system"), exit ( 1);
  9.   if (!status)
  10.    printf ( "shell 不可用\n");
  11.   else
  12.  {
  13.      if ((status = system ( "ls -l")) == -1)
  14. //  if ((status = system ("lss -l")) == -1)
  15. //  if ((status = system ("/home/tarena/project/c_test/shell.sh")) == -1)
  16.    perror ( "system"), exit ( 1);
  17.    printf ( "WEXITSTATUS (status) = %d\n", WEXITSTATUS (status));
  18.  }
  19.   return 0;
  20. }
  21. 输出结果:
  22. 总用量 16
  23. -rwxr-xr-x 1 root root 7308 Apr 27 10: 35 a.out
  24. -rwxrwxrwx 1 root root   19 Apr 27 10: 21 shell.sh
  25. -rw-r--r-- 1 root root  450 Apr 27 10: 35 test. c
  26. WEXITSTATUS (status) = 0
  27. 如果将shell命令错误则,终止状态为 exit( 127)
  28. 输出结果:
  29. sh: 1: lss: not found
  30. WEXITSTATUS (status) = 127

6、示例解析

若 command 参数是一个空指针 (NULL),则仅当命令处理程序可用时,system 返回非 0 值。
通过 if (!status) 判断系统是否支持 system 函数。
如果成功,那么 system 的返回值是 shell 的终止状态,WEXITSTATUS (status) 得到 exit或_exit 参数、return返回值。
再有参数可以是 shell 脚本,也可以是 shell 命令。
如果将shell命令错误则,终止状态为 exit(127).

二、system 进阶

1、system 函数实现


     
     
  1. #include <sys/wait.h>
  2. #include <errno.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. int
  6. system_my (const char *cmdstring)  /* version without signal handling */
  7. {
  8.   pid_t pid;
  9.   int  status;
  10.   if (cmdstring == NULL)
  11.    return( 1);   /* always a command processor with UNIX */
  12.   if ((pid = fork()) < 0) {
  13.   status = -1/* probably out of processes */
  14.  } else if (pid == 0) {     /* child */
  15.   execl( "/bin/sh", "sh", "-c", cmdstring, ( char *) 0);
  16.   _exit( 127);   /* execl error */
  17.  } else {        /* parent */
  18.    while (waitpid(pid, &status, 0) < 0) {
  19.     if (errno != EINTR) {
  20.     status = -1; /* error other than EINTR from waitpid() */
  21.      break;
  22.    }
  23.   }
  24.  }
  25.   return(status);
  26. }
  27. int main (void)
  28. {
  29.   int status;
  30.   if ((status = system_my ( "date")) < 0)
  31.   perror ( "system_my"), exit ( 1);
  32.   if ((status = system_my ( "ls -l")) < 0)
  33.   perror ( "system_my"), exit ( 1);
  34.   return 0;
  35. }
  36. 输出结果:
  37. Thu Apr 27 11: 06: 08 CST 2017
  38. 总用量 16
  39. -rwxr-xr-x 1 root root 7419 Apr 27 11: 06 a.out
  40. -rw-r--r-- 1 root root  862 Apr 27 11: 06 test.c
  41. -rw-r--r-- 1 root root  575 Apr 27 11: 03 test.c~
  42. root@ubuntu:/home/tarena/project/c_test # gedit test.c

2、示例解析

上例说明了 system 实现中调用了 fork、exec 和 waitpid。
其中 shell 的 -c 选项告诉 shell 程序去下一个命令行参数(在这里是 cmdstring)作为命令输入(而不是从标准输入或从一个给定的文件中读命令)。shell 对以 null 字节终止的命令字符串进行语法分析,将它们分成命令行参数。传递给 shell 的实际命令字符串可以包含任一有效的 shell 命令。
如果不使用 shell 执行此命令,而是试图由我们自己执行它,那将相当困难。首先,我们必须用 execlp 而不是 execl,像 shell 那样使用 PATH 变量。我们必须将 null 字节终止的命令字符串分成各个命令行参数,以便调用 execlp。最后,我们也不能使用任何一个 shell 元字符。
注意,我们调用 _exit 而不是 exit。这是为了防止任一标准 I/O 缓冲(这些缓冲会在 fork 中由父进程复制到子进程)在子进程中被冲洗。

3、system 和 fork+exec 比较

使用 system 函数而不直接使用 fork+exec 的好处是,syetem函数针对各种错误和信号都做了必要的处理,而且 system 是标准库函数,可跨平台使用。

与exec的区别
(1)system()和exec()都可以执行进程外的命令,system是在原进程上开辟了一个新的进程,但是exec是用新进程(命令)覆盖了原有的进程
(2)system()和exec()都有能产生返回值,system的返回值并不影响原有进程,但是exec的返回值影响了原进程

三、system 与信号

后续讲到信号部分再来补充!
                                   
                                   
               
                   
  •                                                
  •                                                     点赞                         1                        
  •                        
  •                                                     收藏
  •                        
  •                                                     分享
  •                                                                                                                        
  •                                                        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值