粉丝提问:

彭老师,问下,在程序里面执行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的老铁,抓紧加一口君好友吧!

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

  1. 使用System.Timers.Timer类实现程序定时执行

    使用System.Timers.Timer类实现程序定时执行 在C#里关于定时器类有3个:System.Windows.Forms.Timer类.System.Threading.Timer类和Sys ...

  2. 如何用程序删除win 7下SYSTEM权限的目录

    win7系统由于安装程序等操作,可能会在系统中留下一些所有权限是SYSTEM角色的目录,例如我的系统以前在C盘的QQ卸载后的遗留文件(下图). System是Windows系统中最高权限角色(组),比 ...

  3. Android开发第一讲之目录结构和程序的执行流程

    1.如何在eclipse当中,修改字体 下面的这种办法,可以更改xml的字体 窗口--首选项--常规--外观--颜色和字体--基本--文本字体--编辑Window --> Preferences ...

  4. 在c++程序中执行DOS命令

    转自博客:http://blog.csdn.net/ypist/article/details/8485049 #1,system()方式 在C盘根目录下新建文件夹,名称为12: system(&qu ...

  5. CLR via C# 摘要一:托管程序的执行模型

    托管程序的执行模型大致如下: 编译源代码为程序集(dll或exe文件),程序集包括了记录相关信息的元数据和IL代码 执行程序集文件时,启动CLR,JIT负责把IL编译为本地代码并执行 IL是微软推出的 ...

  6. Java中的static关键字解析(转自海子)__为什么main方法必须是static的,因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  7. [转帖]浅析java程序的执行过程

    浅析java程序的执行过程 转帖来源: https://www.cnblogs.com/wangjiming/p/10315983.html 之前学习过 这一块东西 但是感觉理解的不深刻. copy一 ...

  8. 在Web应用程序中执行计划任务(多线程)

    在业务复杂的应用程序中,有时候会要求一个或者多个任务在一定的时间或者一定的时间间隔内计划进行,比如定时备份或同步数据库,定时发送电子邮件等,我们称之为计划任务.实现计划任务的方法也有很多,可以采用SQ ...

  9. 003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程

    003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程 Java程序长啥样? 首先编写一个Java程序 记事本编写程序 打开记事本 1.wi ...

  10. 多余的Using Namespaces或引用会影响程序的执行效率么?

    在.NET程序编写中,需要using相应命名空间或添加相应的References,可有时候没有使用到的命名空间也被添加到了Using Namespaces中,那么,这样会影响程序的执行效率么? 通过示 ...

随机推荐

  1. 记录一次EF实体跟踪错误

    记录一次EF实体跟踪错误 前言 在我写文章编辑接口的,出现了一个实体跟踪的错误,详情如下 System.InvalidOperationException: The instance of entit ...

  2. ajax - 接口、表单、模板引擎

    1. 今天继续ajax的一个学习,首先明确一个观念,接口,什么是接口,当使用ajax请求数据时,被请求的url就叫做数据接口也就是接口,注意每个接口必须有请求方式,这里有一个接口的测试工具,postm ...

  3. [UG 二次开发 python] 导出BOM表(包含图片)

    只导出最底层的零件,零件的属性已经设置好,零件的截图生成后,放在零件的同一个文件夹下 用到了 xlsxwriter # nx: threaded # 导出BOM表 __version__ = &quo ...

  4. WTM的项目中EFCore如何适配人大金仓数据库

    一.WTM是什么 WalkingTec.Mvvm框架(简称WTM)最早开发与2013年,基于Asp.net MVC3 和 最早的Entity Framework, 当初主要是为了解决公司内部开发效率低 ...

  5. computed 和 watch 的区别和运用的场景?

    computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值: watch: ...

  6. Spring5.X bean自动装配Autowire属性

    属性注入 set方法.构造函数.POJO.list.map.ref,属于手工注入,点我直达 Spring自动注入 使用<bean>元素的autowire属性为一个bean定义指定自动装配模 ...

  7. 动手学Avalonia:基于硅基流动构建一个文生图应用(一)

    文生图 文生图,全称"文字生成图像"(Text-to-Image),是一种AI技术,能够根据给定的文本描述生成相应的图像.这种技术利用深度学习模型,如生成对抗网络(GANs)或变换 ...

  8. Tiny RDM 刚上线就收获一众好评的Redis桌面开源客户端!值得拥有!

    相信对Redis有频繁操作需求的用户,大部分会选择一个顺手的图形化界面工具来代替手动命令行操作以提高效率.Tiny RDM作为一款现代化轻量级的跨平台Redis桌面客户端,为用户提供了便捷高效的Red ...

  9. 网易数帆实时数据湖 Arctic 的探索和实践

    作者 | 蔡芳芳 采访嘉宾 | 马进 网易数帆平台开发专家 数据中台也要从离线为主走向实时化,湖仓一体是第一步. 数据从离线到实时是当前一个很大的趋势,但要建设实时数据.应用实时数据还面临两个难题.首 ...

  10. sed 进阶使用

    sed 进阶使用 工作原理 sed 维护两个数据缓冲区: 活动模式空间 和 辅助保持空间 两者最初都是空的 sed 通过对每一行输入执行以下循环进行操作 从输入流中读取一行,删除任何尾随的换行符,并将 ...