当某个进程打开文件时,操作系统返回相应的文件描述符,进程为了处理该文件必须引用此描述符。
所谓的文件描述符是一个低级的正整数。最前面的三个文件描述符(0,1,2)分别与标准输入(stdin),标准输出(stdout)和标准错误(stderr)对应。
因此,函数 scanf() 使用 stdin,而函数 printf() 使用 stdout。你可以用不同的文件描述符改写默认的设置并重定向进程的 I/O 到不同的文件。
标准输入与输出
执行一个shell命令行时通常会自动打开三个标准文件,即标准输入文件(stdin),通常对应终端的键盘;
标准输出文件(stdout)和标准错误输出文件(stderr),这两个文件都对应终端的屏幕。
进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。
以cat命令为例,cat命令的功能是从命令行给出的文件中读取数据,并将这些数据直接送到标准输出。
若使用如下命令:
$ cat config
将会把文件config的内容依次显示到屏幕上。但是,如果cat的命令行中没有参数,它就会从标准输入中读取数据,并将其送到标准输出。例如:
$ cat
Hello world
Hello world
用户输入的每一行都立刻被cat命令输出到屏幕上。
直接使用标准输入/输出文件存在以下问题:
输入数据从终端输入时,用户费了半天劲输入的数据只能用一次。下次再想用这些数据时就得重新输入。而且在终端上输入时,若输入有误修改起来不是很方便。
输出到终端屏幕上的信息只能看不能动。无法对此输出作更多处理,如将输出作为另一命令的输入进行进一步的处理等。
为了解决上述问题,Linux系统为输入、输出的传送引入了另外两种机制,即输入/输出重定向和管道。
输入重定向
输入重定向是指把命令(或可执行程序)的标准输入重定向到指定的文件中。也就是说,输入可以不来自键盘,而来自一个指定的文件。
所以说,输入重定向主要用于改变一个命令的输入源,特别是改变那些需要大量输入的输入源。
例如,命令wc统计指定文件包含的行数、单词数和字符数。如果仅在命令行上键入:
$ wc
wc将等待用户告诉它统计什么,这时shell就好象死了一样,从键盘键入的所有文本都出现在屏幕上,但并没有什么结果,直至按下ctrl+d,wc才将命令结果写在屏幕上。
如果给出一个文件名作为wc命令的参数,如下例所示,wc将返回该文件所包含的行数、单词数和字符数。
$ wc /etc/passwd
20 23 726 /etc/passwd
另一种把/etc/passwd文件内容传给wc命令的方法是重定向wc的输入。输入重定向的一般形式为:命令<文件名。可以用下面的命令把wc命令的输入重定向为/etc/passwd文件:
$ wc < /etc/passwd
20 23 726
输出重定向
输出重定向是指把命令(或可执行程序)的标准输出或标准错误输出重新定向到指定文件中。这样,该命令的输出就不显示在屏幕上,而是写入到指定文件中。
输出重定向比输入重定向更常用,很多情况下都可以使用这种功能。
例如,如果某个命令的输出很多,在屏幕上不能完全显示,那么将输出重定向到一个文件中,然后再用文本编辑器打开这个文件,就可以查看输出信息;如果想保存一个命令的输出,也可以使用这种方法。
还有,输出重定向可以用于把一个命令的输出当作另一个命令的输入(还有一种更简单的方法,就是使用管道,将在下面介绍)。
输出重定向的一般形式为:命令>文件名。例如:
$ ls > directory.out
$ cat directory.out
ch1.doc ch2.doc ch3.doc chimp config mail/ test/
将ls命令的输出保存为一个名为directory.out的文件。
注:如果>符号后边的文件已存在,那么这个文件将被重写。
为避免输出重定向中指定文件只能存放当前命令的输出重定向的内容,shell提供了输出重定向的一种追加手段。
输出追加重定向与输出重定向的功能非常相似,区别仅在于输出追加重定向的功能是把命令(或可执行程序)的输出结果追加到指定文件的最后,而该文件原有内容不被破坏。
如果要将一条命令的输出结果追加到指定文件的后面,可以使用追加重定向操作符>>。
形式为:命令>>文件名。例如:
$ ls *.doc>>directory.out
$ cat directory.out
ch1.doc ch2.doc ch3.doc chimp config mail/ test/
ch1.doc ch2.doc ch3.doc
和程序的标准输出重定向一样,程序的错误输出也可以重新定向。2>(或2>>)表示对错误输出设备重定向。例如下面的命令:
$ ls /usr/tmp 2> err.file
可在屏幕上看到程序的正常输出结果,但又将程序的任何错误信息送到文件err.file中,以备将来检查用。
还可以使用另一个输出重定向操作符(&>)将标准输出和错误输出同时送到同一文件中。例如:
$ ls /usr/tmp &> output.file
利用重定向将命令组合在一起,可实现系统单个命令不能提供的新功能。例如使用下面的命令序列:
$ ls /usr/bin > /tmp/dir
$ wc -w < /tmp/dir
459
统计了/usr/bin目录下的文件个数。
管道
将一个程序或命令的输出作为另一个程序或命令的输入,有两种方法,
一种是通过一个临时文件将两个命令或程序结合在一起,例如上个例子中的/tmp/dir文件将ls和wc命令联在一起;
另一种是Linux所提供的管道功能。这种方法比前一种方法更好。
管道可以把一系列命令连接起来,这意味着第一个命令的输出会作为第二个命令的输入通过管道传给第二个命令,第二个命令的输出又会作为第三个命令的输入,以此类推。
显示在屏幕上的是管道行中最后一个命令的输出(如果命令行中未使用输出重定向)。
通过使用管道符“|”来建立一个管道行。用管道重写上面的例子:
$ ls /usr/bin|wc -w
1789
命令替换
命令替换和重定向有些相似,但区别在于命令替换是将一个命令的输出作为另外一个命令的参数。常用命令格式为:
command1 `command2`
其中,command2的输出将作为command1的参数。需要注意的是这里的`符号,被它括起来的内容将作为命令执行,执行后的结果作为command1的参数。例如:
$ cd `pwd`
该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
首先说什么是文件描述符,它有什么作用?
文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket。第一个打开的文件是0,第二个是1,依此类推。
Unix 操作系统通常给每个进程能打开的文件数量强加一个限制。更甚的是,unix 通常有一个系统级的限制。
例如:squid 的工作方式,文件描述符的限制可能会极大的影响性能。当squid 用完所有的文件描述符后,它不能接收用户新的连接。
也就是说,用完文件描述符导致拒绝服务。squid 不能接收新请求,直到一部分当前请求完成,相应的文件和socket 被关闭。当squid发现文件描述符短缺时,它会发布警告。
在运行./configure 之前,检查你的系统的文件描述符限制是否合适,能给你避免一些麻烦。
大多数情况下,1024 个文件描述符足够了。非常忙的cache可能需要4096或更多。在配置文件描述符限制时,我推荐设置系统级限制的数量为每个进程限制的2 倍。
2、怎么突破,具体方法?
先查看Linux默认的文件描述符:
# ulimit -n
1024
我们用命令ulimit -HSn 65536来增大文件描述符,然后编译安装squid,把ulimit -HSn 65536放到/etc/rc.d/rc.local让启动时加载。
在Linux下面部署web应用的时候,有时候会遇上Socket/File: Can’t open so many files的问题;
这个值也会影响服务器的最大并发数,其实Linux是有文件句柄限制的,而且Linux默认不是很高,一般都是1024,生产服务器用其实很容易就达到这个数量。
查看方法
我们可以用ulimit -a来查看所有限制值
[root@centos5 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
max nice (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 4096
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
max rt priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 4096
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited||<
其中 "open files (-n) 1024 "是Linux操作系统对一个进程打开的文件句柄数量的限制(也包含打开的SOCKET数量,可影响MySQL的并发连接数目)。
这个值可用ulimit命令来修改,但ulimit命令修改的数值只对当前登录用户的目前使用环境有效,系统重启或者用户退出后就会失效。
(在布署Nginx+FastCGI我就遇到这个问题,将ulimit -SHn 65535放到/etc/rc.d/rc.local也没起什么作用)
系统总限制是在这里,/proc/sys/fs/file-max。可以通过cat查看目前的值,修改/etc/sysctl.conf 中也可以控制。
另外还有一个,/proc/sys/fs/file-nr,可以看到整个系统目前使用的文件句柄数量。
查找文件句柄问题的时候,还有一个很实用的程序lsof。可以很方便看到某个进程开了那些句柄,也可以看到某个文件/目录被什么进程占用了。
修改方法
若要令修改ulimits的数值永久生效,则必须修改配置文档,可以给ulimit修改命令放入/etc/profile里面,这个方法实在是不方便,还有一个方法是修改/etc/sysctl.conf。
我修改了,测试过,但对用户的ulimits -a 是不会改变的,只是/proc/sys/fs/file-max的值变了。
我认为正确的做法,应该是修改/etc/security/limits.conf,里面有很详细的注释,比如
* soft nofile 32768
* hard nofile 65536
就可以将文件句柄限制统一改成软32768,硬65536。配置文件最前面的是指domain,设置为星号代表全局,另外你也可以针对不同的用户做出不同的限制。
注意:这个当中的硬限制是实际的限制,而软限制,是warnning限制,只会做出warning;其实ulimit命令本身就有分软硬设置,加-H就是硬,加-S就是软
默认显示的是软限制,如果运行ulimit命令修改的时候没有加上的话,就是两个参数一起改变。
相关推荐
默认情况下,每个进程都有三个预定义的文件描述符:0(标准输入)、1(标准输出)和2(标准错误),分别用于输入、输出和错误信息。 二、父/子进程对文件描述符的分支使用示例:当一个进程(父进程)调用`fork`创建...
本篇文章将深入探讨Linux文件系统中的某些关键概念,包括特殊文件、文件描述符、文件操作函数以及文件权限。 1. 特殊文件: - `/dev/console`:系统控制台,用于与用户的交互。 - `/dev/tty`:当前终端设备,指向...
1. **标准输入(Standard Input, stdin)**:文件描述符为0,通常与终端的键盘关联,用来接收用户的输入数据。 2. **标准输出(Standard Output, stdout)**:文件描述符为1,通常与终端的屏幕关联,用来展示进程...
在Unix和类Unix系统中,文件描述符通常是一个非负整数,其中0、1、2分别默认指向标准输入、标准输出和标准错误输出。本文将深入探讨与文件描述符操作相关的几个关键概念和特性,特别关注于参数`fd`和`cmd`的使用。 ...
在C语言中,`stdin`(标准输入)、`stdout`(标准输出)和`stderr`(标准错误)是预定义的文件描述符。在示例中,`read()`函数用于从`stdin`读取数据,`write()`函数则将数据写入`stdout`。这段代码实现了将标准输入的内容...
首先,Linux中存在三个基本的文件描述符:标准输入(STDIN)、标准输出(STDOUT)和标准错误(STDERR)。文件描述符 STDIN 的编号为0,标准输入默认设备是键盘;STDOUT 的编号为1,标准输出默认设备是显示器;STDERR...
`poll()`函数是System V的产物,后来被POSIX.1g标准采纳,它克服了`select()`的一些限制,如文件描述符数量的限制。`poll()`使用`pollfd`结构体数组来表示待监控的文件描述符,每个结构体包含一个文件描述符、感兴趣...
Linux 文件操作-系统编程 ...通过学习本章节,读者可以了解 Linux 文件操作的基本概念、文件指针、缓冲区、文件描述符、文件类型、文件操作函数等多方面的知识点,并能够编写基本的文件操作程序。
8. **I/O多路复用**:`select`、`poll`和`epoll`是Linux提供的I/O多路复用机制,它们允许单个线程监控多个文件描述符,一旦有任何描述符就绪,就可以进行I/O操作。 9. **设备驱动**:在更底层,输入输出队列与设备...
4. `dup2()`:复制文件描述符,常用于在父子进程间重定向标准输入/输出/错误。 5. `open()`:打开文件并返回文件描述符。 6. 进程间通信(IPC):使用`sendmsg()`、`recvmsg()`等方法传递文件描述符。 7. 文件权限:...
在Linux系统中,文件I/O(输入/输出)编程是操作系统与应用程序交互的重要部分,它涉及到数据在程序和磁盘之间的传输。以下是对标题和描述中提到的知识点的详细解释: 1. **open()**: `open`函数是用于打开一个文件...
- `2>&1`:运行命令并将标准输出和错误输出合并(通过复制文件描述符1到2实现)。 - `n<&-`:关闭文件描述符`n`的输入。 - `n>&-`:关闭文件描述符`n`的输出。 - **示例**: - `exec 0 exec 1 > outfilename`:...
至于“hid descriptor tool”这个文件名,很可能是该工具的执行程序或者源代码文件,用户可以通过运行或编译这个文件来使用HID描述符自动生成的功能。 USB报告描述符是HID设备的关键部分,它定义了设备如何与主机...
以上内容涵盖了Linux高级编程中的关键知识点,包括文件描述符管理、基本的文件读写操作、输入输出重定向以及网络接口的混杂模式设置等。这些技术对于深入理解Linux操作系统的工作原理及编写高效稳定的程序至关重要。
这些文件描述符通常对应于终端的输入/输出设备,但也可以被重定向到文件或其他设备。 总之,Linux 文件 I/O 操作涉及到的概念和技术非常广泛,包括文件类型、权限管理、系统调用、库函数及系统命令等。了解这些基础...