• 正文
    • system()函數(shù)
    • 程序中如何修改當前程序的工作路徑?
    • 驗證system()
  • 相關推薦
申請入駐 產業(yè)圖譜

在程序里面執(zhí)行system(“cd 某個目錄“),為什么路徑切換不成功?

02/24 15:30
526
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

粉絲提問:彭老師,問下,在程序里面執(zhí)行system("cd /某個目錄"),這樣會切換不成功,為啥呢

實例代碼:

粉絲的疑惑是明明第10行執(zhí)行了cd /media操作,為什么12行執(zhí)行的pwd > test2.txt結果提示的仍然是當前目錄?

這是一個很不錯的問題,要想整明白這個問題,需要知道system的原理。

system()函數(shù)

通過man手冊來查看system庫函數(shù):

由手冊可得:

    system()是庫函數(shù)通過fork()函數(shù)創(chuàng)建子進程在子進程中通過exec族函數(shù)執(zhí)行shell命令

這樣大家就明白了,實際上system執(zhí)行參數(shù)中的字符串代表的命令,
其實是創(chuàng)建了一個進程,然后在子進程中通過exec族函數(shù)來執(zhí)行對應的命令。

當前工作路徑,cwd,可以通過pwd來獲取,

那么工作路徑是和進程相關的,

第10行代碼執(zhí)行之后,雖然確實改變了此時的子進程的工作路徑,

但是隨著子進程的退出該工作路徑已沒有意義,

而執(zhí)行到12行程序的時候,system()又會創(chuàng)建新的子進程,

該子進程仍然繼承父進程的工作路徑,

所以當前工作路徑就沒有變化。

程序中如何修改當前程序的工作路徑?

可以通過函數(shù)chdir()

CHDIR(2)?????????????????????????????????????????????????????????Linux?Programmer's?Manual????????????????????????????????????????????????????????CHDIR(2)

NAME
???????chdir,?fchdir?-?change?working?directory

SYNOPSIS
???????#include?<unistd.h>

???????int?chdir(const?char?*path);
???????int?fchdir(int?fd);

???Feature?Test?Macro?Requirements?for?glibc?(see?feature_test_macros(7)):

???????fchdir():
???????????_BSD_SOURCE?||?_XOPEN_SOURCE?>=?500?||?_XOPEN_SOURCE?&&?_XOPEN_SOURCE_EXTENDED
???????????||?/*?Since?glibc?2.12:?*/?_POSIX_C_SOURCE?>=?200809L

DESCRIPTION
???????chdir()?changes?the?current?working?directory?of?the?calling?process?to?the?directory?specified?in?path.

???????fchdir()?is?identical?to?chdir();?the?only?difference?is?that?the?directory?is?given?as?an?open?file?descriptor.

RETURN?VALUE
???????On?success,?zero?is?returned.??On?error,?-1?is?returned,?and?errno?is?set?appropriately.

該函數(shù)是個系統(tǒng)調用(system是庫函數(shù))。

代碼舉例:

??1?#include?<stdio.h>
??2?#include?<stdlib.h>
??3?#include?<unistd.h>
??4???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
??5?int?main(int?argc,?char?**argv)
??6?{
??7?????system("ls");
??8?????chdir("/");
??9?????system("ls");
?10?????return?0;
?11?}
peng@ubuntu:~/test$?./run?
123.c??a.sh??basic??chat??chris??encryption??net??run??sgm3141?srand
app??boot???dev??home??????initrd.img.old??lib32??libx32?media??opt???root??sbin??srv??tftpboot?usr??vmlinuz???www
bin??cdrom??etc??initrd.img??lib??????lib64??lost+found?mnt????proc??run???snap??sys??tmp?var??vmlinuz.old

由結果可知,8行代碼修改了當前進程的工作路徑為根路徑,
所以第9行執(zhí)行l(wèi)s命令顯示的是根路徑下面的內容

驗證system()

下面我們來看一下,system()這個函數(shù)是如何調用系統(tǒng)調用的。

編寫測試函數(shù)

??1?#include?<stdio.h>
??2?#include?<stdlib.h>???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
??3?
??4?int?main(int?argc,?char?**argv)
??5?{
??6?????system("ls");
??7?????return?0;
??8?}

要想知道某個函數(shù)調用過程,最終調用到哪些系統(tǒng)調用函數(shù),可以借助strace命令

在Linux系統(tǒng)中,strace命令是一個集診斷、調試、統(tǒng)計與一體的工具,可用來追蹤調試程序,能夠與其他命令搭配使用

執(zhí)行結果:

由截圖可知,當我們運行程序時,首先會加載鏈接庫,以便于我們執(zhí)行當前程序,

access("/etc/ld.so.nohwcap",?F_OK)??????=?-1?ENOENT?(No?such?file?or?directory)
access("/etc/ld.so.preload",?R_OK)??????=?-1?ENOENT?(No?such?file?or?directory)
open("/etc/ld.so.cache",?O_RDONLY|O_CLOEXEC)?=?3

最終調用到系統(tǒng)調用函數(shù)clone(),

clone(child_stack=0,?flags=CLONE_PARENT_SETTID|SIGCHLD,?parent_tidptr=0x7fffdff4b59c)?=?2753

并獲取到執(zhí)行結果

wait4(2753,?123.c??a.sh??basic??chat??chris??encryption??net??run??sgm3141?srand

但是前面說了,system不是調用fork的嗎?

man?clone

寫的很清楚了,clone與fork行為一致。

好了,本文就到這。

相關推薦

登錄即可解鎖
  • 海量技術文章
  • 設計資源下載
  • 產業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

公眾號『一口Linux』號主彭老師,擁有15年嵌入式開發(fā)經(jīng)驗和培訓經(jīng)驗。曾任職ZTE,某研究所,華清遠見教學總監(jiān)。擁有多篇網(wǎng)絡協(xié)議相關專利和軟件著作。精通計算機網(wǎng)絡、Linux系統(tǒng)編程、ARM、Linux驅動、龍芯、物聯(lián)網(wǎng)。原創(chuàng)內容基本從實際項目出發(fā),保持原理+實踐風格,適合Linux驅動新手入門和技術進階。