Ⅰ 如何linux 程序中啟用其他進程,非阻塞,非popen
在Linux程序中啟動其他進程可以用system函數,這個函數會等待它啟動的那個程序結束才返回,所以它是一個阻塞調用。還有一種非阻塞的啟動外部程序的方法,稍微復雜一點,是運用Linux的exec系列函數,之所以說系列函數是因為有不同的變種,只是參數的形式不同而已,其實完全是一樣的,exec系列函數的行為是將當前進程替換成要啟動的那個新進程,這里的當前進程就是你編寫的程序,新進程啟動後調用exec函數的進程就不存在了,exec系列函數調用之後的代碼也不會再執行了。所以,exec系列函數的正確使用方法是在程序中進行fork調用復制進程,然後把exec函數的調用語句放在fork的子進程裡面,注意子進程中exec函數調用的後面就不要寫其他功能的代碼了,因為exec函數後面的語句不會被執行。
Ⅱ Linux C語言用system()調用,帶參數
linux c system函數介紹:
system(執行shell 命令)
相關函數
fork,execve,waitpid,popen
表頭文件
#i nclude
定義函數
int system(const char * string);
函數說明
system()會調用fork()產生子進程,由子進程來調用/bin/sh-c string來執行參數string字元串所代表的命令,此命>令執行完後隨即返回原調用的進程。在調用system()期間SIGCHLD 信號會被暫時擱置,SIGINT和SIGQUIT 信號則會被忽略。
返回值
=-1:出現錯誤
=0:調用成功但是沒有出現子進程
>0:成功退出的子進程的id
如果system()在調用/bin/sh時失敗則返回127,其他失敗原因返回-1。若參數string為空指針(NULL),則返回非零值>。如果system()調用成功則最後會返回執行shell命令後的返回值,但是此返回值也有可能為 system()調用/bin/sh失敗所返回的127,因此最好能再檢查errno 來確認執行成功。
附加說明
在編寫具有SUID/SGID許可權的程序時請勿使用system(),system()會繼承環境變數,通過環境變數可能會造成系統安全的問題。
範例
#i nclude
main()
{
system("ls -al /etc/passwd /etc/shadow");
}
執行結果:
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
-r--------- 1 root root 572 Sep 2 15 :34 /etc/shado
例2:
char tmp[];
sprintf(tmp,"/bin/mount -t vfat %s /mnt/usb",dev);
system(tmp);
其中dev是/dev/sda1。
system函數的源碼
#include <syspes.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
int system(const char * cmdstring)
{
pid_t pid;
int status;
if(cmdstring == NULL){
return (1);
}
if((pid = fork())<0){
status = -1;
}
else if(pid = 0){
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
-exit(127); //子進程正常執行則不會執行此語句
}
else
{
while(waitpid(pid, &status, 0) < 0){
if(errno != EINTER)
{
status = -1;
break;
}
}
}
return status;
}
那麼如何獲得system的返回值呢??
char buf[10];
char * ps="ps -ef|grep -c root";
FILE *ptr;
int i;
if((ptr = popen(ps, "r")) != NULL)
{
fgets(buf, 10 , ptr);
i = atoi(buf);
pclose(ptr);
}
可以man下waitpid查看下如何檢查status的值
int ret = system("ls -al /etc/passwd /etc/shadow");
if(WIFSIGNALED(ret))
具體的這些宏查看man waitpid
Ⅲ linux下如何用c語言調用shell命令
參數type可使用「r」代表讀取,「w」代表寫入。依照此type值,popen()會建立管道連到子進程的標准輸出設備或標准輸入設備,然後返回一個文件指針。隨後進程便可利用此文件指針來讀取子進程的輸出設備或是寫入到子進程的標准輸入設備中。此外,所有使用文件指針(FILE*)操作的函數也都可以使用,除了fclose()以外。 返回值:若成功則返迴文件指針,否則返回NULL,錯誤原因存於errno中。 注意:在編寫具SUID/SGID許可權的程序時請盡量避免使用popen(),popen()會繼承環境變數,通過環境變數可能會造成系統安全的問題。 例:C程序popentest.c內容如下: #include main() { FILE * fp; charbuffer[80]; fp=popen(「~/myprogram/test.sh」,」r」); fgets(buffer,sizeof(buffer),fp); printf(「%s」,buffer); pclose(fp); } 執行結果如下: xiakeyou@ubuntu:~/myprogram$ vim popentest.c xiakeyou@ubuntu:~/myprogram$ gcc popentest.c -o popentest xiakeyou@ubuntu:~/myprogram$ ./popentest /home/d/e/xiakeyou xiakeyou@ubuntu:~/myprogram$ 只是偶能力可能有點有限,沒有太看懂。直接用system()倒是腳本可是執行,只是返回值卻是一塌糊塗,試了多次也沒有找到什麼規律。不免又看了一下上面的那篇博文,得到一些啟發,可以這樣來實現: 先將腳本的返回值利用 echo > XXXXX 輸出到一個本地文件中 當需要這個返回值是,可是通過C語言的文件操作函數來直接從文件中讀取 後來一想,這應該就是上文中POPEN的實現方法! C程序調用shell腳本共有三種法子 :system()、popen()、exec系列函數 system() 不用你自己去產生進程,它已經封裝了,直接加入自己的命令exec 需要你自己 fork 進程,然後exec 自己的命令 popen() 也可以實現執行你的命令,比system 開銷小 1)system(shell命令或shell腳本路徑); system()會調用fork()產生 子歷程,由子歷程來調用/bin/sh-c string來履行 參數string字元串所代表的命令,此命令履行 完後隨即返回原調用的歷程。在調用system()期間SIGCHLD 信號會被暫時擱置,SIGINT和SIGQUIT 信號則會被漠視 。 返回值:如果system()在調用/bin/sh時失敗則返回127,其他失敗原因返回-1。若參數string為空指針(NULL),則返回非零值。 如果 system()調用成功 則最後會返回履行 shell命令後的返回值,但是此返回值也有可能為system()調用/bin/sh失敗所返回的127,因 此最好能再反省 errno 來確認履行 成功 。 system命令以其簡略 高效的作用得到很很廣泛 的利用 ,下面是一個例子 例:在~/test/目錄下有shell腳本test.sh,內容為 #!bin/bash #test.sh echo hello 在同層目錄下新建一個c文件system_test.c,內容為: #include int main() { system("~/test/test.sh"); } 履行 效果 如下: [root@localhost test]$gcc system_test.c -o system_test [root@localhost test]$./system_test hello [root@localhost test]$ 2)popen(char *command,char *type) popen()會調用fork()產生 子歷程,然後從子歷程中調用/bin/sh -c來履行 參數command的指令。參數type可應用 「r」代表讀取,「w」代表寫入。遵循此type值,popen()會建立 管道連到子歷程的標准 輸出設備 或標准 輸入設備 ,然後返回一個文件指針。隨後歷程便可利用 此文件指針來讀取子歷程的輸出設備 或是寫入到子歷程的標准 輸入設備 中。此外,所有應用 文 件指針(FILE*)操作的函數也都可以應用 ,除了fclose()以外。 返回值:若成功 則返迴文件指針,否則返回NULL,差錯 原因存於errno中。
Ⅳ 如何在C語言編程中調用linux系統終端下的命令
根據調用需求,可以分為兩種:
一、僅執行系統命令,不需要該命令的列印結果。
這種情況可以用system函數。形式為
system(cmd);
其中cmd為char*類型的字元串,包含要執行的命令,命令的執行結果會輸出到標准輸出。
比如
system("mkdirtest");
這個執行,會在當前文件夾下創建test文件夾。
二、需要命令執行的列印。
雖然同樣可以使用system並重定向到文件,然後打開文件讀取,最終刪除文件。但這樣做比較繁瑣,更好的做法是使用popen。
FILE *fp = popen(cmd);
執行cmd中的命令,然後可以以C文件操作方式,讀取命令的輸出結果。比如:
if((fp=popen("pwd","r"))==NULL)//執行獲取當前目錄的系統命令pwd。
{
printf("執行失敗 ");//fp為NULL表示命令執行失敗。
}
else
{
chars[100];
while(fgets(s,100,fp))//獲取文件內容。
printf("%s",s);//輸出結果。
pclose(fp);//關閉。
}
Ⅳ 怎麼調用system函數,使用Android的linux命令
先來看一下system()函數的簡單介紹:
int system(const char *command);
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
system()函數調用/bin/sh來執行參數指定的命令,/bin/sh 一般是一個軟連接,指向某個具體的shell,比如bash,-c選項是告訴shell從字元串command中讀取命令;
在該command執行期間,SIGCHLD是被阻塞的,好比在說:hi,內核,這會不要給我送SIGCHLD信號,等我忙完再說;
在該command執行期間,SIGINT和SIGQUIT是被忽略的,意思是進程收到這兩個信號後沒有任何動作。
再來看一下system()函數返回值:
The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command otherwise. This latter return status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case /bin/sh could not be executed, the exit status will be that of a command that does exit(127).
If the value of command is NULL, system() returns nonzero if the shell is available, and zero if not.
為了更好的理解system()函數返回值,需要了解其執行過程,實際上system()函數執行了三步操作:
1.fork一個子進程;
2.在子進程中調用exec函數去執行command;
3.在父進程中調用wait去等待子進程結束。
對於fork失敗,system()函數返回-1。
如果exec執行成功,也即command順利執行完畢,則返回command通過exit或return返回的值。
(注意,command順利執行不代表執行成功,比如command:」rm debuglog.txt」,不管文件存不存在該command都順利執行了)
如果exec執行失敗,也即command沒有順利執行,比如被信號中斷,或者command命令根本不存在,system()函數返回127.
如果command為NULL,則system()函數返回非0值,一般為1.
popen和system都可以執行外部命令。
popen相當於是先創建一個管道,fork,關閉管道的一端,執行exec,返回一個標準的io文件指針。
system相當於是先後調用了fork, exec,waitpid來執行外部命令
popen本身是不阻塞的,要通過標准io的讀取使它阻塞
system本身就是阻塞的。
Ⅵ linux下怎樣用c語言調用shell命令
C程序調用shell腳本共同擁有三種法子 :system()、popen()、exec系列數call_exec1.c ,
system() 不用你自己去產生進程。它已經封裝了,直接增加自己的命令
exec 須要你自己 fork 進程,然後exec 自己的命令
popen() 也能夠實現運行你的命令,比system 開銷小
方法一、system()的使用。我直接上代碼吧
int system(const char *command);
我在/home/book/shell新建一個test.sh文件例如以下:
<span style="font-size:18px;"><span style="font-size:18px;">#!bin/bash
echo $HOME
echo "the is test!"</span></span>
test.c文件例如以下:
<span style="font-size:18px;"><span style="font-size:18px;">#include<stdlib.h>
int main()
{
system("bash /home/book/shell/test.sh"); /* chmod +x test.sh ,路徑前面要加上bash */
return 0;
}</span></span>
運行例如以下命令來編譯:
<span style="font-size:18px;">gcc test.c -o test
</span>
測試命令:
<span style="font-size:18px;">./test</span>
結果例如以下:
<span style="font-size:18px;">/root
the is test!</span>
方法二:popen() 會調用fork()產生 子歷程,然後從子歷程中調用/bin/sh -c來履行 參數command的指令。參數type可應用 「r」代表讀取。「w」代表寫入。遵循此type值。popen()會建立 管道連到子歷程的標准 輸出設備 或標准 輸入設備 ,然後返回一個文件指針。
隨後歷程便可利用 此文件指針來讀取子歷程的輸出設備 或是寫入到子歷程的標准 輸入設備 中。此外,全部應用 文 件指針(FILE*)操作的函數也都能夠應用 ,除了fclose()以外。
返回值:若成功 則返迴文件指針,否則返回NULL,差錯 原因存於errno中。注意:在編寫具SUID/SGID許可權的程序時請盡量避免應用 popen()。popen()會繼承環境變數。通過環境變數可能會造成系統安全的問題
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
其它不用改變我們直接改動test.c文件:
#include<stdio.h>
int main()
{
char buffer[80];
FILE *fp=popen("bash /home/book/shell/test.sh","r");
fgets(buffer,sizeof(buffer),fp);
printf("%s",buffer);
pclose(fp);
return 0;
}
方法三:exec函數簇 (我不太懂,別人的。也沒有驗證。習慣方法一)
須要注意的是exec並非1個函數, 事實上它僅僅是一組函數的統稱, 它包含以下6個函數:
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[];
能夠見到這6個函數名字不同, 並且他們用於接受的參數也不同.
實際上他們的功能都是幾乎相同的, 由於要用於接受不同的參數所以要用不同的名字區分它們, 畢竟c語言沒有函數重載的功能嘛..
可是實際上它們的命名是有規律的:
exec[l or v][p][e]
exec函數里的參數能夠分成3個部分, 運行文件部分, 命令參數部分, 環境變數部分.
比如我要運行1個命令 ls -l /home/gateman
運行文件部分就是 "/usr/bin/ls"
命令參賽部分就是 "ls","-l","/home/gateman",NULL 見到是以ls開頭 每1個空格都必須分開成2個部分, 並且以NULL結尾的啊.
環境變數部分, 這是1個數組,最後的元素必須是NULL 比如 char * env[] = {"PATH=/home/gateman", "USER=lei", "STATUS=testing", NULL};
好了說下命名規則:
e興許, 參數必須帶環境變數部分, 環境變零部分參數會成為運行exec函數期間的環境變數, 比較少用
l 興許, 命令參數部分必須以"," 相隔, 最後1個命令參數必須是NULL
v 興許, 命令參數部分必須是1個以NULL結尾的字元串指針數組的頭部指針. 比如char * pstr就是1個字元串的指針, char * pstr[] 就是數組了, 分別指向各個字元串.
關於Linux命令的介紹,看看《linux就該這么學》,具體關於這一章地址3w(dot)linuxprobe/chapter-02(dot)html
p興許, 運行文件部分能夠不帶路徑, exec函數會在$PATH中找
還有1個注意的是, exec函數會代替運行它的進程, 也就是說, 一旦exec函數運行成功, 它就不會返回了, 進程結束. 可是假設exec函數運行失敗, 它會返回失敗的信息, 並且進程繼續運行後面的代碼!
通常exec會放在fork() 函數的子進程部分, 來替代子進程運行啦, 運行成功後子程序就會消失, 可是運行失敗的話, 必須用exit()函數來讓子進程退出!
Ⅶ linux下如何用c語言調用shell命令
在c語言中調用shell命令的方法實現。
c程序調用shell腳本共有兩種方法
:system()、popen(),分別如下:
system()
不用自己去創建進程,系統已經封裝了這一步,直接加入自己的命令即可
popen()
也可以實現執行的命令,比system
開銷小
以下分別說明:
1)system(shell命令或shell腳本路徑);
system()
會調用fork()產生
子歷程,由子歷程來調用/bin/sh-c
string來履行
參數string字元串所代表的命令,此命令履行
完後隨即返回原調用的歷程。在調用system()期間sigchld
信號會被暫時擱置,sigint和sigquit
信號則會被漠視
。
返
回值:如果system()在調用/bin/sh時失敗則返回127,其他失敗原因返回-1。若參數string為空指針(null),則返回非零值。
如果
system()調用成功
則最後會返回履行
shell命令後的返回值,但是此返回值也有可能為system()調用/bin/sh失敗所返回的127,因
此最好能再反省
errno
來確認履行
成功
。
system命令以其簡略
高效的作用得到很很廣泛
的利用
,下面是一個例子
例:在/tmp/testdir/目錄下有shell腳本tsh.sh,內容為
#!/bin/sh
wget
$1
echo
"done!"
2)popen(char
*command,char
*type)
popen()
會調用fork()產生
子歷程,然後從子歷程中調用/bin/sh
-c來履行
參數command的指令。參數type可應用
「r」代表讀取,「w」代表寫入。遵循此type值,popen()會建立
管道連到子歷程的標准
輸出設備
或標准
輸入設備
,然後返回一個文件指針。隨後歷程便可利用
此文件指針來讀取子歷程的輸出設備
或是寫入到子歷程的標准
輸入設備
中。此外,所有應用
文
件指針(file*)操作的函數也都可以應用
,除了fclose()以外。
返回值:若成功
則返迴文件指針,否則返回null,差錯
原因存於errno中。注意:在編寫具suid/sgid許可權的程序時請盡量避免應用
popen(),popen()會繼承環境變數,通過環境變數可能會造成系統安全的問題。
例:c程序popentest.c內容如下:
#include
main
{
file
*
fp;
charbuffer[80];
fp=popen(「~/myprogram/test.sh」,」r」);
fgets(buffer,sizeof(buffer),fp);
printf(「%s」,buffer);
pclose(fp);
}