成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

linux執(zhí)行l(wèi)s會(huì)引起什么系統(tǒng)調(diào)用

這篇文章給大家分享的是有關(guān)linux執(zhí)行l(wèi)s會(huì)引起什么系統(tǒng)調(diào)用的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

目前創(chuàng)新互聯(lián)建站已為上1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管網(wǎng)站運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、冷水灘網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

在linux中,執(zhí)行l(wèi)s會(huì)引起read和exec系統(tǒng)調(diào)用;執(zhí)行任何一個(gè)shell命令都會(huì)調(diào)用fork和exec,但是通過(guò)strace去查看ls引起的系統(tǒng)調(diào)用并沒(méi)有fork,ls命令要列出目錄下的文件,所以要調(diào)用read。

本教程操作環(huán)境:linux7.3系統(tǒng)、Dell G3電腦。

linux執(zhí)行l(wèi)s會(huì)引起什么系統(tǒng)調(diào)用

答案是read、exec系列

shell命令執(zhí)行機(jī)制就是 fork+exec, fork是分身,execve是變身。ls命令要列出目錄下的文件,所以read也會(huì)調(diào)用。

shell訪問(wèn)Linux內(nèi)核就是通過(guò)fork和exec命令實(shí)現(xiàn)的,fork命令創(chuàng)建可以一個(gè)相同的線程出來(lái)。

通過(guò)strace去查看ls引起的系統(tǒng)調(diào)用,確實(shí)是沒(méi)有fork,但是因?yàn)閳?zhí)行任何一個(gè)shell命令都會(huì)調(diào)用fork

execve的變身就是創(chuàng)建一個(gè)新的進(jìn)程,并用新的進(jìn)程去替換掉原來(lái)的進(jìn)程。

首先我們討論一下什么是系統(tǒng)調(diào)用(system calls)?
用戶借助UNIX/linux直接提供的少量函數(shù)可以對(duì)文件和設(shè)備進(jìn)行訪問(wèn)和控制,這些函數(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)用打開(kāi)當(dāng)前目錄文件,返回獲得的文件描述符??梢钥吹皆撐募褂肙_RDONLY標(biāo)志打開(kāi)。

只要該文件是用O_RDONLY或O_RDWR標(biāo)志打開(kāi)的,就可以用read()系統(tǒng)調(diào)用從該文件中讀取字節(jié)[3]。

所以ls要用到read系統(tǒng)調(diào)用。除此之外,任何shell命令都會(huì)創(chuàng)建進(jìn)程,都會(huì)用到exec系統(tǒng)調(diào)用。

回過(guò)頭來(lái)梳理一下我們對(duì)于這些概念可能產(chǎn)生的疑惑:

  1. 包括ls在內(nèi),一個(gè)程序是如何運(yùn)行的?

  2. open系統(tǒng)調(diào)用打開(kāi)當(dāng)前目錄文件,返回獲得的文件描述符。那什么是文件描述符?

1 進(jìn)程是如何運(yùn)行的

每個(gè)運(yùn)行中的程序被稱為進(jìn)程[1]

Unix將進(jìn)程創(chuàng)建與加載一個(gè)新進(jìn)程映象分離。這樣的好處是有更多的余地對(duì)兩種操作進(jìn)行管理。當(dāng)我們創(chuàng)建了一個(gè)進(jìn)程之后,通常將子進(jìn)程替換成新的進(jìn)程映象。所以任何shell命令都會(huì)創(chuàng)建進(jìn)程,都會(huì)用到exec系統(tǒng)調(diào)用。
例如:在shell命令行執(zhí)行ps命令,實(shí)際上是shell進(jìn)程調(diào)用fork復(fù)制一個(gè)新的子進(jìn)程,在利用exec系統(tǒng)調(diào)用將新產(chǎn)生的子進(jìn)程完全替換成ps進(jìn)程。

用exec函數(shù)可以把當(dāng)前進(jìn)程替換為一個(gè)新進(jìn)程,且新進(jìn)程與原進(jìn)程有相同的PID。exec名下是由多個(gè)關(guān)聯(lián)函數(shù)組成的一個(gè)完整系列[4]

調(diào)用fork創(chuàng)建新進(jìn)程后,父進(jìn)程與子進(jìn)程幾乎一模一樣[1,p398]。

fork是一個(gè)UNIX術(shù)語(yǔ),當(dāng)fork一個(gè)進(jìn)程(一個(gè)運(yùn)行中的程序)時(shí),基本上是復(fù)制了它,并且fork后的兩個(gè)進(jìn)程都從當(dāng)前執(zhí)行點(diǎn)繼續(xù)運(yùn)行,并且每個(gè)進(jìn)程都有自己的內(nèi)存副本。

原進(jìn)程是父進(jìn)程,新進(jìn)程是子進(jìn)程??梢酝ㄟ^(guò)fork()返回值區(qū)分。

父進(jìn)程中fork調(diào)用返回的是新的子進(jìn)程的pid(process id),而子進(jìn)程中fork調(diào)用返回的是0

舉個(gè)例子:

#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
*/

如果想要程序啟動(dòng)另一程序的執(zhí)行但自己仍想繼續(xù)運(yùn)行的話,怎么辦呢?那就是結(jié)合fork與exec的使用[6][1, p397]

舉個(gè)例子(修改自[6]):

#include<string.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
#include<unistd.h>
 
 char command[256];
 void main()
 {
    int rtn; /*子進(jìn)程的返回?cái)?shù)值*/
    while(1) {
       /* 從終端讀取要執(zhí)行的命令 */
       printf( ">" );
       fgets( command, 256, stdin );
       command[strlen(command)-1] = 0;
       if ( fork() == 0 ) {/* 子進(jìn)程執(zhí)行此命令 */
          execlp( command, NULL );
          /* 如果exec函數(shù)返回,表明沒(méi)有正常執(zhí)行命令,打印錯(cuò)誤信息*/
          perror( command );
          exit( errno );
       }
       else {/* 父進(jìn)程, 等待子進(jìn)程結(jié)束,并打印子進(jìn)程的返回值 */
          pid_t sonid=wait ( &rtn );
          printf(" child pid: %d\n",sonid);
          printf( " child process return %d\n", rtn );
       }
   }
}

/*output:錯(cuò)誤命令、需要參數(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
*/

先f(wàn)ork,然后子進(jìn)程借助exec調(diào)用程序command。對(duì)錯(cuò)誤命令、需要參數(shù)的命令、以及不需要參數(shù)的命令給出對(duì)應(yīng)的輸出。

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

一切設(shè)備都可以看作文件。

對(duì)內(nèi)核而言,所有打開(kāi)的文件都通過(guò)文件描述符引用[7]。文件描述符是非負(fù)整數(shù),范圍是[0,OPEN_MAX -1]?,F(xiàn)在OPEN_MAX 一般為64

但是[7]又說(shuō)對(duì)于FreeBSD 8.0,Linux 3.2.0 ,Mac OS X 10.6.8等, fd變化范圍幾乎無(wú)限,只受到存儲(chǔ)器數(shù)量、int字長(zhǎng)以及系統(tǒng)管理員所配置的軟限制和硬限制的約束。。。why?

當(dāng)open或者create一個(gè)新文件時(shí),內(nèi)核向進(jìn)程返回一個(gè)文件描述符。

當(dāng)讀、寫(xiě)一個(gè)文件時(shí),使用open或create返回的文件描述符標(biāo)識(shí)該文件,將其作為參數(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)的一個(gè)設(shè)計(jì)標(biāo)準(zhǔn),很多類(lèi)UNIX系統(tǒng)也在支持兼容這個(gè)標(biāo)準(zhǔn),如Linux。
unistd.h是POSIX標(biāo)準(zhǔn)定義的unix類(lèi)系統(tǒng)定義符號(hào)常量的頭文件,包含了許多UNIX系統(tǒng)服務(wù)的函數(shù)原型[5]。在該頭文件,用于訪問(wèn)設(shè)備驅(qū)動(dòng)程序的底層函數(shù)(系統(tǒng)調(diào)用)有這五個(gè):open/close/read/write/ioctl[1]。

4 文件I/O

[7]中提到大多數(shù)文件I/O用到的5個(gè)函數(shù)為:open/read/write/lseek/close

4.1 函數(shù)read

調(diào)用read函數(shù)從打開(kāi)文件中讀數(shù)據(jù)。

#include<unistd.h>
ssize_t read(int filedes, void *buf, size_t nbytes);

返回值:

成功,讀出的字節(jié)數(shù);

失敗,-1;

遇到文件尾,0

有多種情況可使實(shí)際讀到的字節(jié)數(shù)少于要求讀的字節(jié)數(shù):

  • 讀普通文件時(shí),在讀到要求字節(jié)數(shù)之前已經(jīng)到達(dá)了文件尾端。

例如,若在到達(dá)文件尾端之前還有30個(gè)字節(jié),而要求讀100個(gè)字節(jié),則read返回30,下一次再調(diào)用read時(shí),它將回0。

  • 當(dāng)從終端設(shè)備讀時(shí),通常一次最多讀一行

  • 當(dāng)從網(wǎng)絡(luò)讀時(shí),網(wǎng)絡(luò)中的緩沖機(jī)構(gòu)可能造成返回值小于所要求讀的字節(jié)數(shù)。

  • 當(dāng)從管道或FIFO讀時(shí),如若管道包含的字節(jié)少于所需的數(shù)量,那么read將只返回實(shí)際可用的字節(jié)數(shù)。

  • 當(dāng)從某些面向記錄的設(shè)備(例如磁盤(pán))讀時(shí),一次最多返回一個(gè)記錄。

  • 當(dāng)某一信號(hào)造成中斷,而已經(jīng)讀了部分?jǐn)?shù)據(jù)量時(shí)。讀操作從文件的當(dāng)前偏移量出開(kāi)始,在成功返回之前,該偏移量將增加實(shí)際獨(dú)到的字節(jié)數(shù)

read的經(jīng)典原型定義則是:

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

感謝各位的閱讀!關(guān)于“l(fā)inux執(zhí)行l(wèi)s會(huì)引起什么系統(tǒng)調(diào)用”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

名稱欄目:linux執(zhí)行l(wèi)s會(huì)引起什么系統(tǒng)調(diào)用
文章位置:http://jinyejixie.com/article40/ggsoho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)、網(wǎng)站內(nèi)鏈、微信公眾號(hào)網(wǎng)站排名、ChatGPTApp開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)
太康县| 青河县| 中宁县| 南郑县| 大同市| 额济纳旗| 安丘市| 准格尔旗| 宿迁市| 浦东新区| 鄂伦春自治旗| 冷水江市| 诏安县| 左云县| 乌兰县| 乐业县| 体育| 宁海县| 梧州市| 尚志市| 汉寿县| 高雄市| 海伦市| 衢州市| 瑞金市| 广汉市| 昭苏县| 镇安县| 綦江县| 龙门县| 汕尾市| 玉环县| 赣榆县| 和林格尔县| 珠海市| 吉林省| 山丹县| 虞城县| 桐庐县| 常宁市| 宁海县|