這篇文章給大家分享的是有關(guān)linux執(zhí)行l(wèi)s會引起什么系統(tǒng)調(diào)用的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
目前創(chuàng)新互聯(lián)建站已為上1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站運營、企業(yè)網(wǎng)站設(shè)計、冷水灘網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
在linux中,執(zhí)行l(wèi)s會引起read和exec系統(tǒng)調(diào)用;執(zhí)行任何一個shell命令都會調(diào)用fork和exec,但是通過strace去查看ls引起的系統(tǒng)調(diào)用并沒有fork,ls命令要列出目錄下的文件,所以要調(diào)用read。
本教程操作環(huán)境:linux7.3系統(tǒng)、Dell G3電腦。
答案是read、exec系列
shell命令執(zhí)行機制就是 fork+exec, fork是分身,execve是變身。ls命令要列出目錄下的文件,所以read也會調(diào)用。
shell訪問Linux內(nèi)核就是通過fork和exec命令實現(xiàn)的,fork命令創(chuàng)建可以一個相同的線程出來。
通過strace去查看ls引起的系統(tǒng)調(diào)用,確實是沒有fork,但是因為執(zhí)行任何一個shell命令都會調(diào)用fork
execve的變身就是創(chuàng)建一個新的進程,并用新的進程去替換掉原來的進程。
首先我們討論一下什么是系統(tǒng)調(diào)用(system calls)?
用戶借助UNIX/linux直接提供的少量函數(shù)可以對文件和設(shè)備進行訪問和控制,這些函數(shù)就是系統(tǒng)調(diào)用
[1]。
使用strace ls
命令我們可以查看ls命令使用到的系統(tǒng)調(diào)用[2],其中一部分輸出內(nèi)容如下:
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系統(tǒng)調(diào)用打開當(dāng)前目錄文件,返回獲得的文件描述符??梢钥吹皆撐募褂肙_RDONLY標(biāo)志打開。
只要該文件是用O_RDONLY或O_RDWR標(biāo)志打開的,就可以用read()
系統(tǒng)調(diào)用從該文件中讀取字節(jié)[3]。
所以ls
要用到read
系統(tǒng)調(diào)用。除此之外,任何shell命令都會創(chuàng)建進程,都會用到exec系統(tǒng)調(diào)用。
回過頭來梳理一下我們對于這些概念可能產(chǎn)生的疑惑:
包括ls在內(nèi),一個程序是如何運行的?
open系統(tǒng)調(diào)用打開當(dāng)前目錄文件,返回獲得的文件描述符。那什么是文件描述符?
每個運行中的程序被稱為進程[1]
Unix將進程創(chuàng)建與加載一個新進程映象分離。這樣的好處是有更多的余地對兩種操作進行管理。當(dāng)我們創(chuàng)建了一個進程之后,通常將子進程替換成新的進程映象。所以任何shell命令都會創(chuàng)建進程,都會用到exec系統(tǒng)調(diào)用。
例如:在shell命令行執(zhí)行ps命令,實際上是shell進程調(diào)用fork復(fù)制一個新的子進程,在利用exec系統(tǒng)調(diào)用將新產(chǎn)生的子進程完全替換成ps進程。
用exec函數(shù)可以把當(dāng)前進程替換為一個新進程,且新進程與原進程有相同的PID。exec名下是由多個關(guān)聯(lián)函數(shù)組成的一個完整系列[4]
調(diào)用fork創(chuàng)建新進程后,父進程與子進程幾乎一模一樣[1,p398]。
fork是一個UNIX術(shù)語,當(dāng)fork一個進程(一個運行中的程序)時,基本上是復(fù)制了它,并且fork后的兩個進程都從當(dāng)前執(zhí)行點繼續(xù)運行,并且每個進程都有自己的內(nèi)存副本。
原進程是父進程,新進程是子進程??梢酝ㄟ^fork()
返回值區(qū)分。
父進程中fork調(diào)用返回的是新的子進程的pid(process id),而子進程中fork調(diào)用返回的是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 如果想要程序啟動另一程序的執(zhí)行但自己仍想繼續(xù)運行的話,怎么辦呢?那就是結(jié)合fork與exec的使用[6][1, p397]
舉個例子(修改自[6]):
#include#include #include #include #include char command[256]; void main() { int rtn; /*子進程的返回數(shù)值*/ while(1) { /* 從終端讀取要執(zhí)行的命令 */ printf( ">" ); fgets( command, 256, stdin ); command[strlen(command)-1] = 0; if ( fork() == 0 ) {/* 子進程執(zhí)行此命令 */ execlp( command, NULL ); /* 如果exec函數(shù)返回,表明沒有正常執(zhí)行命令,打印錯誤信息*/ perror( command ); exit( errno ); } else {/* 父進程, 等待子進程結(jié)束,并打印子進程的返回值 */ pid_t sonid=wait ( &rtn ); printf(" child pid: %d\n",sonid); printf( " child process return %d\n", rtn ); } } } /*output:錯誤命令、需要參數(shù)命令、正確命令 >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調(diào)用程序command。對錯誤命令、需要參數(shù)的命令、以及不需要參數(shù)的命令給出對應(yīng)的輸出。
2 文件描述符(file descripter,fd)
一切設(shè)備都可以看作文件。
對內(nèi)核而言,所有打開的文件都通過文件描述符引用[7]。文件描述符是非負(fù)整數(shù),范圍是[0,OPEN_MAX -1]?,F(xiàn)在OPEN_MAX 一般為64
但是[7]又說對于FreeBSD 8.0,Linux 3.2.0 ,Mac OS X 10.6.8等, fd變化范圍幾乎無限,只受到存儲器數(shù)量、int字長以及系統(tǒng)管理員所配置的軟限制和硬限制的約束。。。why?
當(dāng)open或者create一個新文件時,內(nèi)核向進程返回一個文件描述符。
當(dāng)讀、寫一個文件時,使用open或create返回的文件描述符標(biāo)識該文件,將其作為參數(shù)傳送給
read / write
按照慣例,fd為0 / 1 / 2分別關(guān)聯(lián)STDIN_FILENO / STDOUT_FILENO / STDERR_FILENO。這些常量也定義在
unistd.h
.3 系統(tǒng)調(diào)用包含在哪些頭文件中呢?
包括exec、fork、read、write在內(nèi),許多系統(tǒng)調(diào)用包含在
unistd.h
頭文件中POSIX,Portable Operating System Interface。是UNIX系統(tǒng)的一個設(shè)計標(biāo)準(zhǔn),很多類UNIX系統(tǒng)也在支持兼容這個標(biāo)準(zhǔn),如Linux。
unistd.h
是POSIX標(biāo)準(zhǔn)定義的unix類系統(tǒng)定義符號常量的頭文件,包含了許多UNIX系統(tǒng)服務(wù)的函數(shù)原型[5]。在該頭文件,用于訪問設(shè)備驅(qū)動程序的底層函數(shù)(系統(tǒng)調(diào)用)有這五個:open/close/read/write/ioctl
[1]。4 文件I/O
[7]中提到大多數(shù)文件I/O用到的5個函數(shù)為:
open/read/write/lseek/close
4.1 函數(shù)read
調(diào)用read函數(shù)從打開文件中讀數(shù)據(jù)。
#includessize_t read(int filedes, void *buf, size_t nbytes); 返回值:
成功,讀出的字節(jié)數(shù);
失敗,-1;
遇到文件尾,0
有多種情況可使實際讀到的字節(jié)數(shù)少于要求讀的字節(jié)數(shù):
讀普通文件時,在讀到要求字節(jié)數(shù)之前已經(jīng)到達了文件尾端。
例如,若在到達文件尾端之前還有30個字節(jié),而要求讀100個字節(jié),則read返回30,下一次再調(diào)用read時,它將回0。
當(dāng)從終端設(shè)備讀時,通常一次最多讀一行
當(dāng)從網(wǎng)絡(luò)讀時,網(wǎng)絡(luò)中的緩沖機構(gòu)可能造成返回值小于所要求讀的字節(jié)數(shù)。
當(dāng)從管道或FIFO讀時,如若管道包含的字節(jié)少于所需的數(shù)量,那么read將只返回實際可用的字節(jié)數(shù)。
當(dāng)從某些面向記錄的設(shè)備(例如磁盤)讀時,一次最多返回一個記錄。
當(dāng)某一信號造成中斷,而已經(jīng)讀了部分?jǐn)?shù)據(jù)量時。讀操作從文件的當(dāng)前偏移量出開始,在成功返回之前,該偏移量將增加實際獨到的字節(jié)數(shù)
read的經(jīng)典原型定義則是:
int read(int fd, char*buf, unsigned nbytes);
感謝各位的閱讀!關(guān)于“l(fā)inux執(zhí)行l(wèi)s會引起什么系統(tǒng)調(diào)用”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
網(wǎng)頁題目:linux執(zhí)行l(wèi)s會引起什么系統(tǒng)調(diào)用
網(wǎng)頁鏈接:http://weahome.cn/article/ggsoho.html