文件描述符,句柄,标准输入,标准输出,标准错误这些其实是相同的东西
句柄是文件描述符的一个别名,标准输入、输出、错误是三个特殊的文件描述符
文件描述符
文件描述符是计算机操作系统中用于标识和访问打开的文件或设备的整数值。它是操作系统为每个进程维护的一种表格数据结构的索引,用于跟踪文件或设备的状态和属性
在Linux系列的操作系统上,由于Linux的设计思想便是把一切设备都视作文件。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。
在Linux内核中会维护一个struct task_struct类型的数组,每个进程对应数组中的一个元素
文件描述符的本质是一个数组下标,其中struct file * filp[NR_OPEN]元素的数组下标NR_OPEN就是文件描述符,在Linux 0.11版本中这个值最大为20
// 以Linux 0.11为例struct task_struct内容如下
struct task_struct {
/* these are hardcoded - don't touch */
long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter;
long priority;
long signal;
struct sigaction sigaction[32];
long blocked; /* bitmap of masked signals */
/* various fields */
int exit_code;
unsigned long start_code,end_code,end_data,brk,start_stack;
long pid,father,pgrp,session,leader;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
long alarm;
long utime,stime,cutime,cstime,start_time;
unsigned short used_math;
/* file system info */
int tty; /* -1 if no tty, so it must be signed */
unsigned short umask;
struct m_inode * pwd;
struct m_inode * root;
struct m_inode * executable;
unsigned long close_on_exec;
struct file * filp[NR_OPEN];
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
struct desc_struct ldt[3];
/* tss for this task */
struct tss_struct tss;
};
标准输入、输出、错误
标准输入、输出、错误是三个特殊的文件描述符
文件描述符在形式上是一个非负整数,标准输入、输出、错误则分别对应0、1、2
| 整数值 | 名称 | <unistd.h>符号常量 | <stdio.h>文件流 |
|---|---|---|---|
| 0 | Standard input | STDIN_FILENO | stdin |
| 1 | Standard output | STDOUT_FILENO | stdout |
| 2 | Standard error | STDERR_FILENO | stderr |
在stdio.h文件中的描述如下
/* Standard streams. */
extern FILE *stdin; /* Standard input stream. */
extern FILE *stdout; /* Standard output stream. */
extern FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdout
#define stderr stderr
在unistd.h文件中描述如下
/* Standard file descriptors. */
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
文件句柄
FILE句柄
对于C/C++来说可以使用FILE结构体指针操作文件句柄,由于FILE结构体通常被认为是一个不透明类型,意味着其内部细节被隐藏起来,用户不能直接访问。FILE结构体的定义和实现细节通常由C库提供。在大多数C库中,包括GNU C库(glibc),FILE结构体仅在标准头文件stdio.h中进行了声明,而没有提供实际的定义。
如果查看FILE.h文件仅能看到FILE结构体的声明,无法看到对应的细节
#ifndef __FILE_defined
#define __FILE_defined 1
struct _IO_FILE;
/* The opaque type of streams. This is the definition used elsewhere. */
typedef struct _IO_FILE FILE;
#endif
通过gcc -E命令直接对stdio.h文件展开可以看到FILE结构体的内部细节
typedef struct _IO_FILE FILE;
struct _IO_FILE
{
int _flags;
char *_IO_read_ptr;
char *_IO_read_end;
char *_IO_read_base;
char *_IO_write_base;
char *_IO_write_ptr;
char *_IO_write_end;
char *_IO_buf_base;
char *_IO_buf_end;
char *_IO_save_base;
char *_IO_backup_base;
char *_IO_save_end;
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
int _flags2;
__off_t _old_offset;
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
_IO_lock_t *_lock;
__off64_t _offset;
struct _IO_codecvt *_codecvt;
struct _IO_wide_data *_wide_data;
struct _IO_FILE *_freeres_list;
void *_freeres_buf;
size_t __pad5;
int _mode;
char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
};
Socket句柄
Socket是用于描述IP地址和端口的通信链的句柄,可用于不同主机间的网络通信也可以用于一台主机的进程间通信
根据通信域的不同可以划分成2种:Unix domain socket 和 Internet domain socket
Internet domain socket用于实现不同主机上的进程间通信Unix domain socket又叫IPC(inter-process communication进程间通信)socket,用于实现同一主机上的进程间通信