粉丝提问:
彭老师,问下,在程序里面执行system("cd /某个目录"),这样会切换不成功,为啥呢
实例代码:
粉丝的疑惑是明明第10行执行了cd /media操作,
为什么12行执行的pwd > test2.txt
结果提示的仍然是当前目录?
这是一个很不错的问题,要想整明白这个问题,需要知道system的原理。
system()函数
通过man手册来查看system库函数:
由手册可得:
- system()是库函数
- 通过fork()函数创建子进程
- 在子进程中通过exec族函数执行shell命令
这样大家就明白了,实际上system执行参数中的字符串代表的命令,
其实是创建了一个进程,然后在子进程中通过exec族函数来执行对应的命令。
当前工作路径,cwd,可以通过pwd来获取,
那么工作路径是和进程相关的,
第10行代码执行之后,虽然确实改变了此时的子进程的工作路径,
但是随着子进程的退出该工作路径已没有意义,
而执行到12行程序的时候,system()又会创建新的子进程,
该子进程仍然继承父进程的工作路径,
所以当前工作路径就没有变化。
程序中如何修改当前程序的工作路径?
可以通过函数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.
该函数是个系统调用(system是库函数)。
代码举例:
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行执行ls命令显示的是根路径下面的内容
验证system()
下面我们来看一下,system()这个函数是如何调用系统调用的。
编写测试函数
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main(int argc, char **argv)
5 {
6 system("ls");
7 return 0;
8 }
要想知道某个函数调用过程,最终调用到哪些系统调用函数,可以借助strace命令
在Linux系统中,strace命令是一个集诊断、调试、统计与一体的工具,可用来追踪调试程序,能够与其他命令搭配使用
执行结果:
由截图可知,
当我们运行程序时,首先会加载链接库,以便于我们执行当前程序,
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
最终调用到系统调用函数clone(),
clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0x7fffdff4b59c) = 2753
并获取到执行结果
wait4(2753, 123.c a.sh basic chat chris encryption net run sgm3141 srand
但是前面说了,system不是调用fork的吗?
man clone
写的很清楚了,clone与fork行为一致。
好了,本文就到这,想学linux的老铁,抓紧加一口君好友吧!
标签:include,int,路径,system,cd,切换,进程,执行 From: https://www.cnblogs.com/yikoulinux/p/17353660.html