最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Linux自定義文件描述符的操作指南

 更新時(shí)間:2025年06月06日 09:16:18   作者:pdudo  
Linux 中一切都可以看作文件,包括普通文件、鏈接文件、Socket 以及設(shè)備驅(qū)動(dòng)等,對(duì)其進(jìn)行相關(guān)操作時(shí),都可能會(huì)創(chuàng)建對(duì)應(yīng)的文件描述符,本文給大家介紹了Linux自定義文件描述符的操作指南,需要的朋友可以參考下

簡(jiǎn)單回顧文件描述符和重定向

linux系統(tǒng)中,為每一個(gè)程序都定義了3個(gè)文件描述符,分別是標(biāo)準(zhǔn)輸入:/dev/stdin、標(biāo)準(zhǔn)輸出:/dev/stdout和錯(cuò)誤輸入:/dev/stderr,如果用文件描述符id表示,則從前到后分別是0、1、2。

linux系統(tǒng)中,可以通過(guò)查詢/proc/進(jìn)程pid/fd下的0、1、2軟連接文件,可以查看文件描述符的具體指向。

# ls -l /proc/$$/fd
total 0
lrwx------. 1 root root 64 Jun  4 22:54 0 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  4 22:54 1 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  4 22:54 2 -> /dev/pts/0
#

在程序初始運(yùn)行中,系統(tǒng)會(huì)為分配這個(gè)3個(gè)文件描述符指向的設(shè)備或者文件,比如在上述例子中,都指向虛擬終端/dev/pts/0,而重定向則是修改文件描述符的指向,比如將標(biāo)準(zhǔn)輸出指向到某個(gè)文件,而后續(xù)程序輸出則會(huì)寫到這個(gè)文件中,當(dāng)然也可以指向其他設(shè)備。

除此之外,還能額外創(chuàng)建其他的文件描述符。

自定義文件描述符的基本操作

在系統(tǒng)中,任何進(jìn)程都可以調(diào)用系統(tǒng)open函數(shù),或者建立新的網(wǎng)絡(luò)連接來(lái)創(chuàng)建文件描述符,而這些文件描述符都屬于該進(jìn)程自己。而在linux中,同樣也可以創(chuàng)建文件描述符,而該文件描述符依然屬于該進(jìn)程,可以看看這二者之間的差別。

進(jìn)程產(chǎn)生的文件描述符

關(guān)于進(jìn)程創(chuàng)建文件描述符,舉一個(gè)最簡(jiǎn)單的例子,比如我們編寫如下的一段go代碼:

package main

import (
	"fmt"
	"net"
	"os"
	"time"
)

func main() {

	fmt.Println("pid: ", os.Getpid())

	for i := 0; i < 10; i++ {
		_, err := os.Create(fmt.Sprintf("file_%d", i))
		if err != nil {
			fmt.Println("open error", err)
		}
	}

	net.Dial("tcp", "192.168.1.1:22")
	net.Dial("tcp", "192.168.1.2:80")

	time.Sleep(time.Hour * 1)

}

上述代碼,首先打印了進(jìn)程的pid,而后在當(dāng)前目錄下新建了file_0file_9這10個(gè)文件,創(chuàng)建了的文件都沒(méi)有進(jìn)行close操作,也就是說(shuō),文件句柄還在進(jìn)程中,然后使用net庫(kù)創(chuàng)建了2個(gè)tcp連接,這是還是沒(méi)有close操作,最后使用sleep睡眠了1個(gè)小時(shí)。

測(cè)試一下進(jìn)程創(chuàng)建文件描述符號(hào),首先進(jìn)行編譯:

go build -o fdtests

而后執(zhí)行該可執(zhí)行文件:

# ./fdtests
pid:  1362

得到了pid之后,新開一個(gè)終端,查看該進(jìn)程的fd信息。

# ls -l /proc/1362/fd/
total 0
lrwx------. 1 root root 64 Jun  4 23:45 0 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  4 23:45 1 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  4 23:45 10 -> /root/file_5
lrwx------. 1 root root 64 Jun  4 23:45 11 -> /root/file_6
lrwx------. 1 root root 64 Jun  4 23:45 12 -> /root/file_7
lrwx------. 1 root root 64 Jun  4 23:45 13 -> /root/file_8
lrwx------. 1 root root 64 Jun  4 23:45 14 -> /root/file_9
lrwx------. 1 root root 64 Jun  4 23:45 15 -> socket:[22365]
lrwx------. 1 root root 64 Jun  4 23:45 16 -> socket:[22366]
lrwx------. 1 root root 64 Jun  4 23:45 2 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  4 23:45 3 -> /root/file_0
lrwx------. 1 root root 64 Jun  4 23:45 4 -> anon_inode:[eventpoll]
lrwx------. 1 root root 64 Jun  4 23:45 5 -> anon_inode:[eventfd]
lrwx------. 1 root root 64 Jun  4 23:45 6 -> /root/file_1
lrwx------. 1 root root 64 Jun  4 23:45 7 -> /root/file_2
lrwx------. 1 root root 64 Jun  4 23:45 8 -> /root/file_3
lrwx------. 1 root root 64 Jun  4 23:45 9 -> /root/file_4
#

通過(guò)上面的例子,可以看到眾多的文件句柄,其中0、1、2分別是系統(tǒng)創(chuàng)建的默認(rèn)的句柄,還可以看到指向文件file_*的句柄,以及2個(gè)socket句柄,是最后的2個(gè)tcp連接。其中有2個(gè)特殊的句柄anon_inode,這個(gè)暫不討論。

上述這些句柄都是屬于進(jìn)程的,其他進(jìn)程是無(wú)法直接使用的,也需要調(diào)用系統(tǒng)open函數(shù)來(lái)實(shí)現(xiàn)自己的句柄才行。

使用命令創(chuàng)建的文件描述符

linux中,會(huì)為每一個(gè)進(jìn)程都分配0、12 這三個(gè)文件描述符,包括使用的終端,而自定義的文件描述符必須從3開始,而linux建議使用39這幾個(gè)文件描述符,當(dāng)然,這只是建議,你可以不遵守,只要?jiǎng)?chuàng)建的文件描述符id不超過(guò)系統(tǒng)允許最大的值即可,在linux系統(tǒng)中使用如下命令查詢?cè)试S最大的文件描述符:

ulimit -n

當(dāng)然也可以動(dòng)態(tài)修改它,比如將其修改為65535,只需要在n的后面添加即可:

ulimit -n 65535

創(chuàng)建文件描述符

linux中,創(chuàng)建一個(gè)可讀可寫的文件描述符,使用<>關(guān)鍵字即可,例如:

exec 3<>/root/a.log

如上命令創(chuàng)建了一個(gè)可讀可寫的文件描述符3,指向/root/a.log,在linux中創(chuàng)建的文件描述符是在/dev/fd目錄中,例如:

# ls -l /dev/fd/
total 0
lrwx------. 1 root root 64 Jun  5 23:47 0 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  5 23:47 1 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  5 23:47 2 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  5 23:47 3 -> /root/a.log
lr-x------. 1 root root 64 Jun  5 23:47 4 -> /proc/1852/fd
#

注意,該目錄/dev/fd是一個(gè)虛擬目錄,不同的進(jìn)程查看該目錄會(huì)得到不一樣的結(jié)果,即:該目錄下的句柄,只能創(chuàng)建該句柄的進(jìn)程所使用,其他進(jìn)程均無(wú)法使用。

向文件描述符寫入數(shù)據(jù)

使用重定向?qū)懭雰?nèi)容,比如上面文件描述符id3,即:

echo "123" >& 3

注意,>&是一個(gè)關(guān)鍵字,表示向文件描述符寫入數(shù)據(jù),而3則表示文件描述符id,注意:沒(méi)有>>&這種寫法,這種寫法是錯(cuò)誤的。

如果要將一個(gè)標(biāo)準(zhǔn)錯(cuò)誤的數(shù)據(jù)寫入到對(duì)應(yīng)的文件描述符中,需要用到2>&關(guān)鍵字,即:

abcd 2>& 3

都知道沒(méi)有abcd這個(gè)命令,所以解釋權(quán)會(huì)向錯(cuò)誤輸出報(bào)錯(cuò)找不到命令,使用2>&將該報(bào)錯(cuò)寫入到文件描述符id3中。

文件描述符讀取數(shù)據(jù)

使用<&關(guān)鍵字可以讀取文件描述符的內(nèi)容,比如:

cat <& 3

可以讀取文件描述符id3的內(nèi)容,但是實(shí)際執(zhí)行后,你會(huì)發(fā)現(xiàn),什么內(nèi)容都沒(méi)有,如:

# cat <& 3
#

這是因?yàn)?code>linux中有一個(gè)叫做文件指針的概念(offset),在向該文件描述符寫入內(nèi)容的時(shí)候,已經(jīng)同步將指針移動(dòng)了到了最后,所以在讀取的時(shí)候,什么內(nèi)容也沒(méi)有。需要重置offset為開頭,即重新設(shè)置一下文件描述符:

# exec 3<>/root/a.log
# cat <& 3
123
-bash: abcd: command not found
#

如下即可讀取到文件描述符指向文件的內(nèi)容了。

關(guān)閉文件描述符

使用如下命令可以關(guān)閉id3的文件描述符:

exec 3>&-

其中,3>&-不能有任何空格,否則會(huì)報(bào)錯(cuò)。

關(guān)閉后,/dev/fd/文件中就沒(méi)有相關(guān)文件的文件描述符了。

# ls -l /dev/fd/
total 0
lrwx------. 1 root root 64 Jun  5 23:49 0 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  5 23:49 1 -> /dev/pts/0
lrwx------. 1 root root 64 Jun  5 23:49 2 -> /dev/pts/0
lr-x------. 1 root root 64 Jun  5 23:49 3 -> /proc/1293/fd
#

創(chuàng)建只讀、只寫文件描述符

上述是創(chuàng)建了一個(gè)可讀寫的文件測(cè)試服,文件指針會(huì)隨著寫入變化而變化,linux還允許創(chuàng)建只讀、只寫的文件描述符,比如:

創(chuàng)建只寫文件描述符id5,指向文件/root/a1.log,命令如下:

# exec 5> /root/a1.log

可以使用查看/dev/fd/5權(quán)限,如下:

# ls -l /dev/fd/5
l-wx------. 1 root root 64 Jun  5 23:49 /dev/fd/5 -> /root/a1.log
#

其中它的權(quán)限為-wx,只有寫和執(zhí)行權(quán)限,沒(méi)有讀權(quán)限。

所以,若讀取的話,會(huì)報(bào)錯(cuò):

# cat <& 5
cat: -: Bad file descriptor
#

創(chuàng)建只讀文件描述符id6,同樣指向文件/root/a1.log,命令如下:

# exec 6< /root/a1.log

同樣的,該文件權(quán)限只有讀和執(zhí)行權(quán)限,沒(méi)有寫權(quán)限。

# ls -l /dev/fd/6
lr-x------. 1 root root 64 Jun  5 23:47 /dev/fd/6 -> /root/a1.log
#

這個(gè)時(shí)候使用文件描述符5來(lái)寫數(shù)據(jù),使用文件描述符6來(lái)去讀數(shù)據(jù)。

# echo '123' >& 5
# cat <& 6
123
# cat <& 6
#

讀取完成后,文件指針會(huì)移動(dòng)到讀取后的位置,所以重復(fù)讀取是沒(méi)有用的。

文件描述符小例子

使用命名管道來(lái)限制多進(jìn)程同時(shí)執(zhí)行,代碼如下:

#!/bin/bash

mkfifo pipe

exec 3<>./pipe

for i in $(seq 2)
do
        echo "${i}" >&3
done

for i in $(seq 10)
do
{
        read -u 3 id
        echo id: ${id} time: $(date +"%F %T") id: ${i}
        sleep 3
        echo ${id} >&3
}&
done

exec 3>&-

wait

rm -f pipe

echo "done"

上述腳本利用了管道來(lái)限制多進(jìn)程同時(shí)執(zhí)行,首先使用mkdifo是用來(lái)創(chuàng)建管道,而后定義了一個(gè)文件描述符id3來(lái)指向該管道文件,第一個(gè)for循環(huán)表示允許同時(shí)最多幾個(gè)進(jìn)程運(yùn)行,上述定義的是2個(gè),而后定義了10個(gè)進(jìn)程來(lái)同時(shí)運(yùn)行,使用read -u來(lái)讀取文件描述符指向文件的內(nèi)容,并且寫入id變量,當(dāng)read讀取不到管道數(shù)據(jù)數(shù)據(jù)的時(shí)候,會(huì)阻塞當(dāng)前進(jìn)程,由于提前寫入了2個(gè)數(shù)據(jù),所以,只允許2個(gè)進(jìn)程同時(shí)運(yùn)行,并且執(zhí)行完畢后,將id重新寫入到管道中,以便實(shí)現(xiàn)循環(huán)讀取。最后關(guān)閉文件描述符,刪除管道文件。

所以上述腳本執(zhí)行結(jié)果如下:

[root@localhost bash]# bash fd_test.sh
id: 1 time: 2025-06-05 23:47:46 id: 7
id: 2 time: 2025-06-05 23:47:46 id: 3
id: 1 time: 2025-06-05 23:47:49 id: 2
id: 2 time: 2025-06-05 23:47:49 id: 4
id: 1 time: 2025-06-05 23:47:52 id: 6
id: 2 time: 2025-06-05 23:47:52 id: 5
id: 1 time: 2025-06-05 23:47:55 id: 1
id: 2 time: 2025-06-05 23:47:55 id: 8
id: 1 time: 2025-06-05 23:47:58 id: 10
id: 2 time: 2025-06-05 23:47:58 id: 9
done
[root@localhost bash]#

可以通過(guò)輸出發(fā)現(xiàn),同一時(shí)間只有2個(gè)任務(wù)在同時(shí)運(yùn)行。

總結(jié)

linux中,每個(gè)進(jìn)程打開文件、建立網(wǎng)絡(luò)連接,其實(shí)都是在文件描述符中增加相應(yīng)的id,若超過(guò)系統(tǒng)設(shè)置的值,則會(huì)報(bào)錯(cuò)Too many open files

linux中,可以手動(dòng)指定文件描述符,相關(guān)操作如下,比如創(chuàng)建id3的文件描述符各項(xiàng)操作:

創(chuàng)建只讀的文件描述符:

exec 3<filename

創(chuàng)建只寫的文件描述符:

exec 3>filename

創(chuàng)建可讀寫的文件描述符:

exec 3<>filename

進(jìn)行文件描述符讀取操作:

<&3

進(jìn)行文件描述符寫入操作:

>&3

最后是關(guān)閉文件描述符:

3>&-

最后介紹了一個(gè)小例子,使用文件描述符配合管道來(lái)實(shí)現(xiàn)控制shell腳本的同時(shí)運(yùn)行。

以上就是Linux自定義文件描述符的操作指南的詳細(xì)內(nèi)容,更多關(guān)于Linux自定義文件描述符的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Linux服務(wù)器操作系統(tǒng)加固方法

    Linux服務(wù)器操作系統(tǒng)加固方法

    本幫助手冊(cè)旨在指導(dǎo)系統(tǒng)管理人員或安全檢查人員進(jìn)行Linux操作系統(tǒng)的安全合規(guī)性檢查和加固,需要的朋友可以參考下
    2018-02-02
  • Linux下如何生成coredump文件

    Linux下如何生成coredump文件

    這篇文章主要介紹了Linux下如何生成coredump文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Ubuntu20.04點(diǎn)擊文件閃退的解決方案

    Ubuntu20.04點(diǎn)擊文件閃退的解決方案

    在Ubuntu系統(tǒng)下,如果點(diǎn)擊文件按鈕導(dǎo)致系統(tǒng)閃退,可以嘗試更新系統(tǒng)和應(yīng)用程序、重置文件管理器、檢查系統(tǒng)日志、檢查系統(tǒng)文件和依賴項(xiàng)、切換到不同的文件管理器以及檢查顯卡驅(qū)動(dòng)等方法來(lái)解決問(wèn)題
    2026-02-02
  • Linux之軟件包管理器yum詳解

    Linux之軟件包管理器yum詳解

    文章介紹了現(xiàn)代類Unix操作系統(tǒng)中軟件包管理和包存儲(chǔ)庫(kù)的工作原理,以及如何使用包管理器如yum來(lái)安裝、更新和卸載軟件,文章還介紹了如何配置yum源,更新系統(tǒng)軟件包和查看已安裝的軟件
    2025-01-01
  • 詳解Linux如何查看當(dāng)前占用CPU或內(nèi)存最多的幾個(gè)進(jìn)程

    詳解Linux如何查看當(dāng)前占用CPU或內(nèi)存最多的幾個(gè)進(jìn)程

    本篇文章主要介紹了詳解Linux如何查看當(dāng)前占用CPU或內(nèi)存最多的幾個(gè)進(jìn)程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • linux分析服務(wù)器內(nèi)存常用命令與查找文件工作路徑方式

    linux分析服務(wù)器內(nèi)存常用命令與查找文件工作路徑方式

    文章介紹了如何使用`auditd`服務(wù)查看內(nèi)存使用情況,并通過(guò)`ps`命令按內(nèi)存使用排行,此外,還說(shuō)明了通過(guò)進(jìn)程的工作目錄(cwd)來(lái)定位文件位置,從而確定服務(wù)的具體位置
    2025-10-10
  • Hadoop streaming詳細(xì)介紹

    Hadoop streaming詳細(xì)介紹

    這篇文章主要介紹了Hadoop streaming詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Linux 掛載磁盤詳解及實(shí)操步驟

    Linux 掛載磁盤詳解及實(shí)操步驟

    Linux中掛載磁盤是一項(xiàng)重要的操作,可以用于擴(kuò)展存儲(chǔ)空間,管理數(shù)據(jù)文件,備份和存儲(chǔ)重要文件等,本文將詳細(xì)介紹Linux系統(tǒng)中掛載磁盤的相關(guān)概念、步驟和實(shí)際操作指南
    2023-06-06
  • 在Linux下搜索大文件和目錄的常用方法

    在Linux下搜索大文件和目錄的常用方法

    在Linux上,您可能希望查找占用太多空間的大文件或目錄,本指南將向您展示如何使用終端命令搜索這些大文件和目錄,需要的朋友可以參考下
    2026-02-02
  • ubuntu22.04?server安裝及使用詳細(xì)圖文教程

    ubuntu22.04?server安裝及使用詳細(xì)圖文教程

    這篇文章主要給大家介紹了關(guān)于ubuntu22.04?server安裝及使用的相關(guān)資料,Ubuntu Server是Ubuntu家族的一員,專為網(wǎng)絡(luò)和服務(wù)量身定制,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10

最新評(píng)論

婺源县| 普兰店市| 杨浦区| 泗阳县| 赤水市| 大田县| 富顺县| 青川县| 东明县| 普兰县| 依兰县| 西峡县| 洪雅县| 元朗区| 天气| 沅陵县| 仁化县| 当雄县| 搜索| 宝山区| 彩票| 蒲城县| 酉阳| 从江县| 易门县| 治县。| 建始县| 建阳市| 象州县| 阜南县| 宜兰市| 新干县| 前郭尔| 泌阳县| 龙井市| 循化| 漾濞| 志丹县| 西乌珠穆沁旗| 余姚市| 嘉荫县|