首页 > 编程语言 >在程序里面执行system(“cd /某个目录“),为什么路径切换不成功?

在程序里面执行system(“cd /某个目录“),为什么路径切换不成功?

时间:2023-04-25 19:56:17浏览次数:37  
标签:include int 路径 system cd 切换 进程 执行

粉丝提问:

彭老师,问下,在程序里面执行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

相关文章

  • linux操作系统分析实验五-深入理解进程切换
    Lab5:深入理解进程切换首先找到对应进程调度的代码文件Kernal/sched/core.c  找到context_switch()函数   其中包括rq,为进程的runningqueue;以及进程切换前后的进程描述符prev和next  首先调用一些函数做上下文切换的准备,与最后出现的finish_task_switch()成......
  • 名字修饰约定: extern "C"、extern "C++" 和__stdcall、__cdecl相关的约定、__imp_前
    关于extern_C通常,在C语言的头文件中经常可以看到类似下面这种形式的代码#ifdef__cplusplusextern"C"{#endif/****somedeclarationorso*****/#ifdef__cplusplus}#endif/*endof__cplusplus*/那么,这种写法什么用呢?实际上,这是为了让CPP能够与C......
  • Linux性能优化篇-了解CPU上下文切换
     我们了解到导致平均负载,有可能是以下几种方面:CPU密集型(造成cpu利用率升高,可以理解)I/O密集型(io和cpu互斥的,也造成cpu利用率增高-不可中断进程的)大量进程(???)根据平均负载的解释,单位时间内的处于可运行的进程和不可中断进程的进程数,Systemloadaveragesistheaveragenumberofproc......
  • Ubuntu 22.04.1 LTS 切换国内源
    1、备份原文件cp/etc/apt/sources.list/etc/apt/sources.list.bak 2、清空 sources.list文件中的内容,然后将以下任何一个源复制到文件中,以阿里源为例:vim/etc/apt/sources.listdebhttp://mirrors.aliyun.com/ubuntu/jammymainrestricteduniversemultiversed......
  • 在jupyter notebook中切换PY版本
    首先,确保已经成功安装完了Condacondaenvlist #查看当前已经创建的py环境condaactivatepaddle242#切换到需要使用的py环境pipinstallipykernel python-mipykernelinstall--user--name<PY的环境名称>--display-name<Jupyter的环境名称>example:python-mip......
  • Unity框架:JKFrame2.0学习笔记(十一)——MonoSystem(1)
    内部结构MonoSystemMonoSystem是继承MonoBehaviour的,声明几个action,在MonoBehaviour的声明周期内调用,实现了不继承MonoBehaviour也可以用mono的生命周期。包括以下几个方法可供外部调用:Init:初始化,获取MonoSystem的实例AddUpdateListener:添加Update监听RemoveUpdateListener:移除Upd......
  • 拒绝“千人一面”!使用CDP实现市场细分助力GMV增长
    哈佛商学院在美国进行的一项调查发现,95%的新品牌失败是由于无效的营销细分,其失败的原因在于每个消费者都是独立的个体,他们也有着独特的要求。因此,千人一面的营销策略无法吸引所有用户。而成功品牌总是会向正确的消费者提供正确的产品,为此,营销人员需要彻底了解他们的客户,市场细分可......
  • authentication required to refresh system repositories
     安装完centos8后,图形界面不时出现如下的要求输入密码的验证 解决办法:cd/etc/polkit-1/localauthority/50-local.d/vi46-allow-packagekit.pkla内容如下:[AllowRefreshRepositoryallUsers]Identity=unix-user:*Action=org.freedesktop.packagekit.system-sou......
  • K8s 集群 etcd节点故障解决方案
    1环境说明k8s版本:v1.20etcd节点(192.168.0.12)故障: 报错详情: 4月2422:47:13k8s-node2etcd[9543]:{"level":"warn","ts":"2023-04-24T22:47:13.571+0800","caller":"etcdserver/server.go:2065","msg":......
  • 使用ansible-playbook自动化安装proxysql+replication manager切换MySQL
    【proxysql+replicationmanager切换MySQL】【剧本说明】以下文件在roles目录下treeproxysql/proxysql/├──defaults│└──main.yml├──files│└──rpms│├──proxysql-2.4.1-1-centos7.x86_64.rpm│└──replication-manager-osc-cgo-2......