在linux系統下的操作中我們會經常用到shell命令來進行,一開始學習進程的時候對於shell命令也進行了思考,認為shell命令就是一個進程的外殼,經過了后來的學習對於這一點也有了更多的認識。
用過shell命令的都是知道,shell命令有很多,比如去一個目錄中文件名的列表是用ls,新建一個文件夾用mkdir等。其實,我們用的shell命令“ls”、“-c”就是shell這個程序的參數,下面我們通過編程來實現shell中的ls命令並將結果寫到temp.txt文件中。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/wait.h> #define MAX 1024 int system(const char * cmdstring); int main(void) { int fd , n; char buf[MAX]; //保存文件內容的緩沖區 if(system("ls > temp.txt") == -1){ //使用system執行ls命令,並將結果輸出到temp.txt文件中 perror("fail to exec command"); exit(1); } if((fd = open("temp.txt",O_RDWR)) == -1){//打開temp.txt文件 perror("fail to open"); exit(1); } printf("%d\n",fd); if((n = read(fd, buf ,MAX)) == -1){ //讀文件內容 perror("fail to read"); exit(1); } buf[n] = '\0'; //添加'\0'結束符 printf("%s",buf); //文件內容自帶'\n' return 0; }
這一部分是通過調用system函數實現shell中的ls命令,這一部分是簡單的函數調用、文件讀寫和顯示。這里的system函數就相當於是shell,system函數的執行流程分為兩部分,首先調用system函數的進程創建一個子進程,並且調用wait函數等待子進程執行完畢。其次是在子進程中調用excel函數加在shell運行cmdstring中的指令,程序如下。
//system1函數的原理性實現 int system(const char * cmdstring) { pid_t pid; int status; if(cmdstring == NULL) //如果命令字符串為空,則返回1 return 1; pid = fork(); //創建一個子進程 if(pid < 0){ status = -1; }else if(pid == 0){ //子進程 execl("/bin/sh","sh","-c",cmdstring,NULL); //加載shell,由shell執行命令 _exit(127); //如果執行程序失敗,子程序退出,返回127 } if(waitpid(pid, &status, 0) == -1) //wait函數出錯,拋棄得到的無用狀態 status = -1; return status; //返回退出狀態 }
上邊的程序可以看出這一段原理性實現的主要部分就是子進程這一部分代碼的程序,在子進程中加載shell執行命令。