文件流和 文件描述符

文件流和 文件描述符

#include"apue.h"
int glob=6;
int main(void)
{
        int var;
        pid_t pid;
        int i;
        char buf[200];

        var=88;
        printf("before vfork\n");
        if((pid=vfork())<0){
                err_sys("vfork error");
        }else if(pid==0){
                glob++;
                var++;
                fclose(stdout);                   //(1)
                _exit(0);
        }
        i = printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
        sprintf(buf, "%d\n", i);
        write(STDOUT_FILENO, buf, strlen(buf));
        exit(0);

}
程序的运行结果如下:
$ ./a.out
before vfork
-1

 

stdin是标准输入文件,stdout是标准输出文件,stderr标准出错文件,应用在输出的重新定位上。

程序按如下方式使用这些文件:

标准输入是程序可以读取其输入的位置。缺省情况下,进程从键盘读取 stdin。

标准输出是程序写入其输出的位置。缺省情况下,进程将 stdout 写到终端屏幕上。

标准错误是程序写入其错误消息的位置。缺省情况下,进程将 stderr 写到终端屏幕上。


文件描述符:如果我们用fd表示,该fd可以是open、pipe、dup、dup2和creat等调用返回的结果,在linux系统中,设备也是以文件的形式存在,要对该设备进行操作就必须先打开这个文件,打开这个文件就会,就会获得这个文件描述符,它是个很小的正整数,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。文件描述符的优点:兼容POSIX标准,许多Linux和 UNIX系统调用都依赖于它。文件描述符的缺点:不能移植到UNIX以外的系统上去,也不直观。

fd只是一个索引.


文件指针:  C语言中使用的是文件指针而不是文件描述符做为I/O的句柄." 文件指针(file pointer)"指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括一个缓冲区和一个文件描述符值.而文件描述符值是文件描述符表中的一个索引.从某种意义上说文件指针就是句柄的句柄。
用下面的流图可以说明问题: (ps: 虽然不是流图关系,但是还是有助于理解)

printf -> stdout -> STDOUT_FILENO(1) -> 终端(tty)

 

 

stdout/stdin -- 标准输出输入设备 (printf("..")) 。
stderr -- 标准错误输出设备

两者默认向屏幕输出。
但如果用转向标准输出到磁盘文件,则可看出两者区别。stdout输出到磁盘文件,stderr在屏幕。
printf最后的输出到了终端设备,文件描述符1指向当前的终端可以这么理解:

STDOUT_FILENO = open("/dev/tty", O_RDWR);

 

stdout/stdin类型为 FILE*
STDOUT_FILENO类型为 int
使用stdout/stdin的函数主要有:fread、fwrite、fclose等,基本上都以f开头
使用STDIN_FILENO的函数有:read、write、close等

  fwrite(buf,strlen(buf), 1,stdout);
  write(STDOUT_FILENO,&buf,strlen(buf));


总结:注释(1)的fclose 只关闭了stdout,而没有关闭STDOUT_FILENO,所以write() 仍然可以写到STDOUT_FILENO中.
但是把(1)处改为close(STDOUT_FILENO),程序输出变为:
./a.out
before vfork
pid = 28003, glob = 7, var = 89
32

 

文件描述符和文件流之间的转换   FILE *fdopen(int fildes, const char *type);
这个函数很有用的,功能是将一个流关联到一个打开的文件号filedes上,

该filedes可以是open、pipe、dup、dup2和creat等调用返回的结果
type指定流打开方式,同fopen的打开方式,如"a", "r","w"等等
fdopen的流打开方式服从filedes的打开方式,比如filedes的open指定O_RDONLY,那么fdopen也只能指定"r"的打开方式了。
用fdopen的好处很明显,如果你不得已只能打开文件号,比如socket或者dup调用,但又想用fprintf,fscanf等流操作来进行读写,那么就再fdopen一次好了。

int fileno(FILE stream);
用fileno有什么好处呢?你用fopen打开了文件,但是又想用flock或者lockf来给文件加锁,或者用fcntl来进行某些底层的操作,但上述这些函数只能对打开的文件号操作,而不能对打开流,这时候就用fileno再flock、lockf、fcntl好了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值