在linux中,执行ls会引起read和exec系统调用;执行任何一个shell命令都会调用fork和exec,但是通过strace去查看ls引起的系统调用并没有fork,ls命令要列出目录下的文件,所以要调用read。
本教程操作环境: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系统调用。
回过头来梳理一下我们对于这些概念可能产生的疑惑:
- 包括ls在内,一个程序是如何运行的?
- 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<unistd.h> #include<stdio.h> #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<LEN;i++) { pid_t id1=getpid(); printf("%d ",id1); printf("Child process:%d\n",i); } } else { printf("res %d\n",res); for(i=0;i<LEN;i++) { pid_t id2=getpid(); printf("%d ",id2); printf("parent process:%d\n",i); } } printf("THE END\n"); return 0; } /*output Main pid: 10965 res 10966 10965 parent process:0 10965 parent process:1 10965 parent process:2 10965 parent process:3 10965 parent process:4 10965 parent process:5 10965 parent process:6 10965 parent process:7 10965 parent process:8 10965 parent process:9 10966 Child process:0 10966 Child process:1 THE END 10966 Child process:2 10966 Child process:3 10966 Child process:4 10966 Child process:5 10966 Child process:6 10966 Child process:7 10966 Child process:8 10966 Child process:9 THE END */
如果想要程序启动另一程序的执行但自己仍想继续运行的话,怎么办呢?那就是结合fork与exec的使用[6][1, p397]
举个例子(修改自[6]):
#include<string.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include<unistd.h> 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: 11247 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一个新文件时,内核向进程返回一个文件描述符。
当读、写一个文件时,使用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<unistd.h> 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视频教程》
以上是linux执行ls会引起哪些系统调用的详细内容。更多信息请关注PHP中文网其他相关文章!

Linux中不可或缺的命令包括:1.ls:列出目录内容;2.cd:改变工作目录;3.mkdir:创建新目录;4.rm:删除文件或目录;5.cp:复制文件或目录;6.mv:移动或重命名文件或目录。这些命令通过与内核交互执行操作,帮助用户高效管理文件和系统。

在Linux中,文件和目录管理使用ls、cd、mkdir、rm、cp、mv命令,权限管理使用chmod、chown、chgrp命令。1.文件和目录管理命令如ls-l列出详细信息,mkdir-p递归创建目录。2.权限管理命令如chmod755file设置文件权限,chownuserfile改变文件所有者,chgrpgroupfile改变文件所属组。这些命令基于文件系统结构和用户、组系统,通过系统调用和元数据实现操作和控制。

MaintenancemodeInuxisAspecialBootenvironmentforforcalsystemmaintenancetasks.itallowsadMinistratorStoperFormTaskSlikerSettingPassingPassingPasswords,RepairingFilesystems,andRecoveringFrombootFailuresFailuresFailuresInamInimAlenimalenimalenrenmentrent.ToEnterMainterMainterMaintErmaintErmaintEncemememodeBoode,Interlecttheboo

Linux的核心组件包括内核、文件系统、Shell、用户空间与内核空间、设备驱动程序以及性能优化和最佳实践。1)内核是系统的核心,管理硬件、内存和进程。2)文件系统组织数据,支持多种类型如ext4、Btrfs和XFS。3)Shell是用户与系统交互的命令中心,支持脚本编写。4)用户空间与内核空间分离,确保系统稳定性。5)设备驱动程序连接硬件与操作系统。6)性能优化包括调整系统配置和遵循最佳实践。

Linux系统的五个基本组件是:1.内核,2.系统库,3.系统实用程序,4.图形用户界面,5.应用程序。内核管理硬件资源,系统库提供预编译函数,系统实用程序用于系统管理,GUI提供可视化交互,应用程序利用这些组件实现功能。

Linux的维护模式可以通过GRUB菜单进入,具体步骤为:1)在GRUB菜单中选择内核并按'e'编辑,2)在'linux'行末添加'single'或'1',3)按Ctrl X启动。维护模式提供了一个安全环境,适用于系统修复、重置密码和系统升级等任务。

进入Linux恢复模式的步骤是:1.重启系统并按特定键进入GRUB菜单;2.选择带有(recoverymode)的选项;3.在恢复模式菜单中选择操作,如fsck或root。恢复模式允许你以单用户模式启动系统,进行文件系统检查和修复、编辑配置文件等操作,帮助解决系统问题。

Linux的核心组件包括内核、文件系统、Shell和常用工具。1.内核管理硬件资源并提供基本服务。2.文件系统组织和存储数据。3.Shell是用户与系统交互的接口。4.常用工具帮助完成日常任务。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Atom编辑器mac版下载
最流行的的开源编辑器

禅工作室 13.0.1
功能强大的PHP集成开发环境