0

0

linux执行ls会引起哪些系统调用

WBOY

WBOY

发布时间:2022-03-18 11:05:00

|

4394人浏览过

|

来源于php中文网

原创

在linux中,执行ls会引起read和exec系统调用;执行任何一个shell命令都会调用fork和exec,但是通过strace去查看ls引起的系统调用并没有fork,ls命令要列出目录下的文件,所以要调用read。

linux执行ls会引起哪些系统调用

本教程操作环境:linux7.3系统、Dell G3电脑。

linux执行ls会引起哪些系统调用

答案是read、exec系列

shell命令执行机制就是 fork+exec, fork是分身,execve是变身。ls命令要列出目录下的文件,所以read也会调用。

shell访问Linux内核就是通过fork和exec命令实现的,fork命令创建可以一个相同的线程出来。

通过strace去查看ls引起的系统调用,确实是没有fork,但是因为执行任何一个shell命令都会调用fork

execve的变身就是创建一个新的进程,并用新的进程去替换掉原来的进程。

首先我们讨论一下什么是系统调用(system calls)?
用户借助UNIX/linux直接提供的少量函数可以对文件和设备进行访问和控制,这些函数就是系统调用[1]。

使用strace ls命令我们可以查看ls命令使用到的系统调用[2],其中一部分输出内容如下:

open(".", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
getdents64(3, /* 68 entries */, 32768)  = 2240
getdents64(3, /* 0 entries */, 32768)   = 0
close(3)                                = 0

open系统调用打开当前目录文件,返回获得的文件描述符。可以看到该文件使用O_RDONLY标志打开。

只要该文件是用O_RDONLY或O_RDWR标志打开的,就可以用read()系统调用从该文件中读取字节[3]。

所以ls要用到read系统调用。除此之外,任何shell命令都会创建进程,都会用到exec系统调用。

回过头来梳理一下我们对于这些概念可能产生的疑惑:

  1. 包括ls在内,一个程序是如何运行的?
  2. open系统调用打开当前目录文件,返回获得的文件描述符。那什么是文件描述符?

1 进程是如何运行的

每个运行中的程序被称为进程[1]

Unix将进程创建与加载一个新进程映象分离。这样的好处是有更多的余地对两种操作进行管理。当我们创建了一个进程之后,通常将子进程替换成新的进程映象。所以任何shell命令都会创建进程,都会用到exec系统调用。
例如:在shell命令行执行ps命令,实际上是shell进程调用fork复制一个新的子进程,在利用exec系统调用将新产生的子进程完全替换成ps进程。

用exec函数可以把当前进程替换为一个新进程,且新进程与原进程有相同的PID。exec名下是由多个关联函数组成的一个完整系列[4]

调用fork创建新进程后,父进程与子进程几乎一模一样[1,p398]。

fork是一个UNIX术语,当fork一个进程(一个运行中的程序)时,基本上是复制了它,并且fork后的两个进程都从当前执行点继续运行,并且每个进程都有自己的内存副本。

原进程是父进程,新进程是子进程。可以通过fork()返回值区分。

父进程中fork调用返回的是新的子进程的pid(process id),而子进程中fork调用返回的是0

举个例子:

#include
#include
#define LEN 10
int main()
{
    pid_t id=getpid();
    printf("Main pid: %d \n",id);
	int i;
	pid_t res=fork();
	if(res==0)
	{
	  for(i =0;i

如果想要程序启动另一程序的执行但自己仍想继续运行的话,怎么办呢?那就是结合fork与exec的使用[6][1, p397]

举个例子(修改自[6]):

#include
 #include 
 #include 
 #include 
#include
 
 char command[256];
 void main()
 {
    int rtn; /*子进程的返回数值*/
    while(1) {
       /* 从终端读取要执行的命令 */
       printf( ">" );
       fgets( command, 256, stdin );
       command[strlen(command)-1] = 0;
       if ( fork() == 0 ) {/* 子进程执行此命令 */
          execlp( command, NULL );
          /* 如果exec函数返回,表明没有正常执行命令,打印错误信息*/
          perror( command );
          exit( errno );
       }
       else {/* 父进程, 等待子进程结束,并打印子进程的返回值 */
          pid_t sonid=wait ( &rtn );
          printf(" child pid: %d\n",sonid);
          printf( " child process return %d\n", rtn );
       }
   }
}

/*output:错误命令、需要参数命令、正确命令
>aa
aa: No such file or directory
 child pid: 11230
 child process return 512
>echo
A NULL argv[0] was passed through an exec system call.
 child pid: 11231
 child process return 134
>ps
 child pid: 11241247
 child process return 139
*/

先fork,然后子进程借助exec调用程序command。对错误命令、需要参数的命令、以及不需要参数的命令给出对应的输出。

2 文件描述符(file descripter,fd)

一切设备都可以看作文件。

对内核而言,所有打开的文件都通过文件描述符引用[7]。文件描述符是非负整数,范围是[0,OPEN_MAX -1]。现在OPEN_MAX 一般为64

但是[7]又说对于FreeBSD 8.0,Linux 3.2.0 ,Mac OS X 10.6.8等, fd变化范围几乎无限,只受到存储器数量、int字长以及系统管理员所配置的软限制和硬限制的约束。。。why?

当open或者create一个新文件时,内核向进程返回一个文件描述符。

谱乐AI
谱乐AI

谱乐AI,集成 Suno、Udio 等顶尖AI音乐模型的一站式AI音乐生成平台。

下载

当读、写一个文件时,使用open或create返回的文件描述符标识该文件,将其作为参数传送给read / write

按照惯例,fd为0 / 1 / 2分别关联STDIN_FILENO / STDOUT_FILENO / STDERR_FILENO。这些常量也定义在unistd.h.

3 系统调用包含在哪些头文件中呢?

包括exec、fork、read、write在内,许多系统调用包含在unistd.h头文件中

POSIX,Portable Operating System Interface。是UNIX系统的一个设计标准,很多类UNIX系统也在支持兼容这个标准,如Linux。
unistd.h是POSIX标准定义的unix类系统定义符号常量的头文件,包含了许多UNIX系统服务的函数原型[5]。在该头文件,用于访问设备驱动程序的底层函数(系统调用)有这五个:open/close/read/write/ioctl[1]。

4 文件I/O

[7]中提到大多数文件I/O用到的5个函数为:open/read/write/lseek/close

4.1 函数read

调用read函数从打开文件中读数据。

#include
ssize_t read(int filedes, void *buf, size_t nbytes);

返回值:

成功,读出的字节数;

失败,-1;

遇到文件尾,0

有多种情况可使实际读到的字节数少于要求读的字节数:

  • 读普通文件时,在读到要求字节数之前已经到达了文件尾端。

例如,若在到达文件尾端之前还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它将回0。

  • 当从终端设备读时,通常一次最多读一行

  • 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。

  • 当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么read将只返回实际可用的字节数。

  • 当从某些面向记录的设备(例如磁盘)读时,一次最多返回一个记录。

  • 当某一信号造成中断,而已经读了部分数据量时。读操作从文件的当前偏移量出开始,在成功返回之前,该偏移量将增加实际独到的字节数

read的经典原型定义则是:

int read(int fd, char*buf, unsigned nbytes);

相关推荐:《Linux视频教程

相关专题

更多
Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

37

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

37

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

16

2026.01.13

PHP缓存策略教程大全
PHP缓存策略教程大全

本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

交互式图表和动态图表教程汇总
交互式图表和动态图表教程汇总

本专题整合了交互式图表和动态图表的相关内容,阅读专题下面的文章了解更多详细内容。

45

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

9

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.1万人学习

Git 教程
Git 教程

共21课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号