在程序里面执行system(“cd /某个目录“),为什么路径切换不成功?
来源:一口Linux发布时间:2023-04-24978浏览
询问 AI彭老师,问下,在程序里面执行system("cd /某个目录"),这样会切换不成功,为啥呢

实例代码:
粉丝的疑惑是明明第10行执行了cd /media操作,为什么12行执行的pwd > test2.txt结果提示的仍然是当前目录?
这是一个很不错的问题,要想整明白这个问题,需要知道system的原理。
通过man手册来查看system库函数:
由手册可得:
- system()是库函数
- 通过fork()函数创建子进程
- 在子进程中通过exec族函数执行shell命令
这样大家就明白了,实际上system执行参数中的字符串代表的命令,其实是创建了一个进程,然后在子进程中通过exec族函数来执行对应的命令。
当前工作路径,cwd,可以通过pwd来获取,
那么工作路径是和进程相关的,
第10行代码执行之后,虽然确实改变了此时的子进程的工作路径,
但是随着子进程的退出该工作路径已没有意义,
而执行到12行程序的时候,system()又会创建新的子进程,
该子进程仍然继承父进程的工作路径,
所以当前工作路径就没有变化。
可以通过函数chdir()
CHDIR(2)LinuxProgrammer'sManualCHDIR(2)
NAME
chdir,fchdir-changeworkingdirectory
SYNOPSIS
#include<unistd.h>
intchdir(constchar*path);
intfchdir(intfd);
FeatureTestMacroRequirementsforglibc(seefeature_test_macros(7)):
fchdir():
_BSD_SOURCE||_XOPEN_SOURCE>=500||_XOPEN_SOURCE_XOPEN_SOURCE_EXTENDED
||/*Sinceglibc2.12:*/_POSIX_C_SOURCE>=200809L
DESCRIPTION
chdir()changesthecurrentworkingdirectoryofthecallingprocesstothedirectoryspecifiedinpath.
fchdir()isidenticaltochdir();theonlydifferenceisthatthedirectoryisgivenasanopenfiledescriptor.
RETURNVALUE
Onsuccess,zeroisreturned.Onerror,-1isreturned,anderrnoissetappropriately.
该函数是个系统调用(system是库函数)。
代码举例:
1#include<stdio.h>
2#include<stdlib.h>
3#include<unistd.h>
4
5intmain(intargc,char**argv)
6{
7system("ls");
8chdir("/");
9system("ls");
10return0;
11}
peng@ubuntu:~/test$./run
123.ca.shbasicchatchrisencryptionnetrunsgm3141srand
appbootdevhomeinitrd.img.oldlib32libx32mediaoptrootsbinsrvtftpbootusrvmlinuzwww
bincdrometcinitrd.imgliblib64lost+foundmntprocrunsnapsystmpvarvmlinuz.old
由结果可知,8行代码修改了当前进程的工作路径为根路径,所以第9行执行ls命令显示的是根路径下面的内容
下面我们来看一下,system()这个函数是如何调用系统调用的。
编写测试函数
1#include<stdio.h>
2#include<stdlib.h>
3
4intmain(intargc,char**argv)
5{
6system("ls");
7return0;
8}
要想知道某个函数调用过程,最终调用到哪些系统调用函数,可以借助strace命令
在Linux系统中,strace命令是一个集诊断、调试、统计与一体的工具,可用来追踪调试程序,能够与其他命令搭配使用
执行结果:
由截图可知,当我们运行程序时,首先会加载链接库,以便于我们执行当前程序,
access("/etc/ld.so.nohwcap",F_OK)=-1ENOENT(Nosuchfileordirectory)
access("/etc/ld.so.preload",R_OK)=-1ENOENT(Nosuchfileordirectory)
open("/etc/ld.so.cache",O_RDONLY|O_CLOEXEC)=3
最终调用到系统调用函数clone(),
clone(child_stack=0,flags=CLONE_PARENT_SETTID|SIGCHLD,parent_tidptr=0x7fffdff4b59c)=2753
并获取到执行结果
wait4(2753,123.ca.shbasicchatchrisencryptionnetrunsgm3141srand
但是前面说了,system不是调用fork的吗?
manclone
写的很清楚了,clone与fork行为一致。
敬请关注!
想学linux的老铁,抓紧加一口君好友吧!
新闻来源:一口Linux,文中所述为作者独立观点,不代表icspec立场。更多精彩资讯请下载icspec App。如对本稿件有异议,请联系微信客服specltkj。

