📄 library_12.html
字号:
You must make sure that the <VAR>opentype</VAR> argument matches the actualmode of the open file descriptor.<P>The return value is the new stream. If the stream cannot be created(for example, if the modes for the file indicated by the file descriptordo not permit the access specified by the <VAR>opentype</VAR> argument), anull pointer is returned instead.<P>For an example showing the use of the <CODE>fdopen</CODE> function,see section <A HREF="library_14.html#SEC212" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_14.html#SEC212">Creating a Pipe</A>.<P><A NAME="IDX654"></A><U>Function:</U> int <B>fileno</B> <I>(FILE *<VAR>stream</VAR>)</I><P>This function returns the file descriptor associated with the stream<VAR>stream</VAR>. If an error is detected (for example, if the <VAR>stream</VAR>is not valid) or if <VAR>stream</VAR> does not do I/O to a file,<CODE>fileno</CODE> returns <CODE>-1</CODE>.<P><A NAME="IDX655"></A><A NAME="IDX656"></A><P>There are also symbolic constants defined in <TT>`unistd.h'</TT> for thefile descriptors belonging to the standard streams <CODE>stdin</CODE>,<CODE>stdout</CODE>, and <CODE>stderr</CODE>; see section <A HREF="library_11.html#SEC119" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_11.html#SEC119">Standard Streams</A>.<A NAME="IDX657"></A><P><DL COMPACT><A NAME="IDX658"></A><DT><CODE>STDIN_FILENO</CODE><DD>This macro has value <CODE>0</CODE>, which is the file descriptor forstandard input.<A NAME="IDX659"></A><P><A NAME="IDX660"></A><DT><CODE>STDOUT_FILENO</CODE><DD>This macro has value <CODE>1</CODE>, which is the file descriptor forstandard output.<A NAME="IDX661"></A><P><A NAME="IDX662"></A><DT><CODE>STDERR_FILENO</CODE><DD>This macro has value <CODE>2</CODE>, which is the file descriptor forstandard error output.<A NAME="IDX663"></A></DL><P><A NAME="IDX664"></A><A NAME="IDX665"></A><A NAME="IDX666"></A><A NAME="IDX667"></A><H2><A NAME="SEC176" HREF="library_toc.html#SEC176" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC176">Precautions for Mixing Streams and Descriptors</A></H2><P>You can have multiple file descriptors and streams (let's call bothstreams and descriptors "channels" for short) connected to the samefile, but you must take care to avoid confusion between channels. Thereare two cases to consider: <DFN>linked</DFN> channels that share a singlefile position value, and <DFN>independent</DFN> channels that have their ownfile positions.<P>It's best to use just one channel in your program for actual datatransfer to any given file, except when all the access is for input.For example, if you open a pipe (something you can only do at the filedescriptor level), either do all I/O with the descriptor, or construct astream from the descriptor with <CODE>fdopen</CODE> and then do all I/O withthe stream.<P><A NAME="IDX668"></A><H3><A NAME="SEC177" HREF="library_toc.html#SEC177" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC177">Linked Channels</A></H3><P>Channels that come from a single opening share the same file position;we call them <DFN>linked</DFN> channels. Linked channels result when youmake a stream from a descriptor using <CODE>fdopen</CODE>, when you get adescriptor from a stream with <CODE>fileno</CODE>, and when you copy adescriptor with <CODE>dup</CODE> or <CODE>dup2</CODE>. For files that don't supportrandom access, such as terminals and pipes, <EM>all</EM> channels areeffectively linked. On random-access files, all append-type outputstreams are effectively linked to each other.<A NAME="IDX669"></A><P>If you have been using a stream for I/O, and you want to do I/O usinganother channel (either a stream or a descriptor) that is linked to it,you must first <DFN>clean up</DFN> the stream that you have been using.See section <A HREF="library_12.html#SEC179" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_12.html#SEC179">Cleaning Streams</A>.<P>Terminating a process, or executing a new program in the process,destroys all the streams in the process. If descriptors linked to thesestreams persist in other processes, their file positions becomeundefined as a result. To prevent this, you must clean up the streamsbefore destroying them.<P><A NAME="IDX670"></A><H3><A NAME="SEC178" HREF="library_toc.html#SEC178" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC178">Independent Channels</A></H3><P>When you open channels (streams or descriptors) separately on a seekablefile, each channel has its own file position. These are called<DFN>independent channels</DFN>.<P>The system handles each channel independently. Most of the time, thisis quite predictable and natural (especially for input): each channelcan read or write sequentially at its own place in the file.The precautions you should take are these:<P><UL><LI>You should clean an output stream after use, before doing anything elsethat might read or write from the same part of the file.<P><LI>You should clean an input stream before reading data that may have beenmodified using an independent channel. Otherwise, you might readobsolete data that had been in the stream's buffer.</UL><P>If you do output to one channel at the end of the file, this willcertainly leave the other independent channels positioned somewherebefore the new end. If you want them to output at the end, you must settheir file positions to end of file, first. (This is not necessary ifyou use an append-type descriptor or stream; they always output at thecurrent end of the file.) In order to make the end-of-file positionaccurate, you must clean the output channel you were using, if it is astream. (This is necessary even if you plan to use an append-typechannel next.)<P>It's impossible for two channels to have separate file pointers for afile that doesn't support random access. Thus, channels for reading orwriting such files are always linked, never independent. Append-typechannels are also always linked. For these channels, follow the rulesfor linked channels; see section <A HREF="library_12.html#SEC177" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_12.html#SEC177">Linked Channels</A>.<P><H3><A NAME="SEC179" HREF="library_toc.html#SEC179" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC179">Cleaning Streams</A></H3><P>On the GNU system, you can clean up any stream with <CODE>fclean</CODE>:<P><A NAME="IDX671"></A><U>Function:</U> int <B>fclean</B> <I>(<VAR>stream</VAR>)</I><P>Clean up the stream <VAR>stream</VAR> so that its buffer is empty. If<VAR>stream</VAR> is doing output, force it out. If <VAR>stream</VAR> is doinginput, give the data in the buffer back to the system, arranging toreread it.<P>On other systems, you can use <CODE>fflush</CODE> to clean a stream in mostcases.<P>You can skip the <CODE>fclean</CODE> or <CODE>fflush</CODE> if you know the streamis already clean. A stream is clean whenever its buffer is empty. Forexample, an unbuffered stream is always clean. An input stream that isat end-of-file is clean. A line-buffered stream is clean when the lastcharacter output was a newline.<P>There is one case in which cleaning a stream is impossible on mostsystems. This is when the stream is doing input from a file that is notrandom-access. Such streams typically read ahead, and when the file isnot random access, there is no way to give back the excess data alreadyread. When an input stream reads from a random-access file,<CODE>fflush</CODE> does clean the stream, but leaves the file pointer at anunpredictable place; you must set the file pointer before doing anyfurther I/O. On the GNU system, using <CODE>fclean</CODE> avoids both ofthese problems.<P>Closing an output-only stream also does <CODE>fflush</CODE>, so this is avalid way of cleaning an output stream. On the GNU system, closing aninput stream does <CODE>fclean</CODE>.<P>You need not clean a stream before using its descriptor for controloperations such as setting terminal modes; these operations don't affectthe file position and are not affected by it. You can use anydescriptor for these operations, and all channels are affectedsimultaneously. However, text already "output" to a stream but stillbuffered by the stream will be subject to the new terminal modes whensubsequently flushed. To make sure "past" output is covered by theterminal settings that were in effect at the time, flush the outputstreams for that terminal before setting the modes. See section <A HREF="library_16.html#SEC272" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_16.html#SEC272">Terminal Modes</A>.<P><A NAME="IDX672"></A><A NAME="IDX673"></A><A NAME="IDX674"></A><H2><A NAME="SEC180" HREF="library_toc.html#SEC180" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC180">Waiting for Input or Output</A></H2><P>Sometimes a program needs to accept input on multiple input channelswhenever input arrives. For example, some workstations may have devicessuch as a digitizing tablet, function button box, or dial box that areconnected via normal asynchronous serial interfaces; good user interfacestyle requires responding immediately to input on any device. Anotherexample is a program that acts as a server to several other processesvia pipes or sockets.<P>You cannot normally use <CODE>read</CODE> for this purpose, because thisblocks the program until input is available on one particular filedescriptor; input on other channels won't wake it up. You could setnonblocking mode and poll each file descriptor in turn, but this is veryinefficient.<P>A better solution is to use the <CODE>select</CODE> function. This blocks theprogram until input or output is ready on a specified set of filedescriptors, or until timer expires, whichever comes first. Thisfacility is declared in the header file <TT>`sys/types.h'</TT>.<A NAME="IDX675"></A><A NAME="IDX676"></A><P>The file descriptor sets for the <CODE>select</CODE> function are specifiedas <CODE>fd_set</CODE> objects. Here is the description of the data typeand some macros for manipulating these objects.<P><A NAME="IDX677"></A><U>Data Type:</U> <B>fd_set</B><P>The <CODE>fd_set</CODE> data type represents file descriptor sets for the<CODE>select</CODE> function. It is actually a bit array.<P><A NAME="IDX678"></A><U>Macro:</U> int <B>FD_SETSIZE</B><P>The value of this macro is the maximum number of file descriptors that a<CODE>fd_set</CODE> object can hold information about. On systems with afixed maximum number, <CODE>FD_SETSIZE</CODE> is at least that number. Onsome systems, including GNU, there is no absolute limit on the number ofdescriptors open, but this macro still has a constant value whichcontrols the number of bits in an <CODE>fd_set</CODE>.<P><A NAME="IDX679"></A><U>Macro:</U> void <B>FD_ZERO</B> <I>(fd_set *<VAR>set</VAR>)</I><P>This macro initializes the file descriptor set <VAR>set</VAR> to be theempty set.<P><A NAME="IDX680"></A><U>Macro:</U> void <B>FD_SET</B> <I>(int <VAR>filedes</VAR>, fd_set *<VAR>set</VAR>)</I><P>This macro adds <VAR>filedes</VAR> to the file descriptor set <VAR>set</VAR>.<P><A NAME="IDX681"></A><U>Macro:</U> void <B>FD_CLR</B> <I>(int <VAR>filedes</VAR>, fd_set *<VAR>set</VAR>)</I><P>This macro removes <VAR>filedes</VAR> from the file descriptor set <VAR>set</VAR>.<P><A NAME="IDX682"></A><U>Macro:</U> int <B>FD_ISSET</B> <I>(int <VAR>filedes</VAR>, fd_set *<VAR>set</VAR>)</I><P>This macro returns a nonzero value (true) if <VAR>filedes</VAR> is a memberof the the file descriptor set <VAR>set</VAR>, and zero (false) otherwise.<P>Next, here is the description of the <CODE>select</CODE> function itself.<P><A NAME="IDX683"></A><U>Function:</U> int <B>select</B> <I>(int <VAR>nfds</VAR>, fd_set *<VAR>read_fds</VAR>, fd_set *<VAR>write_fds</VAR>, fd_set *<VAR>except_fds</VAR>, struct timeval *<VAR>timeout</VAR>)</I><P>The <CODE>select</CODE> function blocks the calling process until there isactivity on any of the specified sets of file descriptors, or until thetimeout period has expired.<P>The file descriptors specified by the <VAR>read_fds</VAR> argument arechecked to see if they are ready for reading; the <VAR>write_fds</VAR> filedescriptors are checked to see if they are ready for writing; and the<VAR>except_fds</VAR> file descriptors are checked for exceptionalconditions. You can pass a null pointer for any of these arguments ifyou are not interested in checking for that kind of condition.<P>"Exceptional conditions" does not mean errors--errors are reportedimmediately when an erroneous system call is executed, and do notconstitute a state of the descriptor. Rather, they include conditionssuch as the presence of an urgent message on a socket. (See section <A HREF="library_15.html#SEC216" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_15.html#SEC216">Sockets</A>,for information on urgent messages.)<P>The <CODE>select</CODE> function checks only the first <VAR>nfds</VAR> filedescriptors. The usual thing is to pass <CODE>FD_SETSIZE</CODE> as the valueof this argument.<P>The <VAR>timeout</VAR> specifies the maximum time to wait. If you pass anull pointer for this argument, it means to block indefinitely until oneof the file descriptors is ready. Otherwise, you should provide thetime in <CODE>struct timeval</CODE> format; see section <A HREF="library_19.html#SEC315" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_19.html#SEC315">High-Resolution Calendar</A>. Specify zero as the time (a <CODE>struct timeval</CODE> containingall zeros) if you want to find out which descriptors are ready withoutwaiting if none are ready.<P>The normal return value from <CODE>select</CODE> is the total number of ready filedescriptors in all of the sets. Each of the argument sets is overwrittenwith information about the descriptors that are ready for the correspondingoperation. Thus, to see if a particular descriptor <VAR>desc</VAR> has input,use <CODE>FD_ISSET (<VAR>desc</VAR>, <VAR>read_fds</VAR>)</CODE> after <CODE>select</CODE> returns.<P>If <CODE>select</CODE> returns because the timeout period expires, it returns
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -