关于fd和fp(fd:file descirptor fp:file pointor)

通常,我们在输入数据或输出数据的设备为键盘或者显示器。当然,我们比较熟悉的输入输出,可能就是对于文件的操作,还有直接从终端输出,显示到显示器上。在C语言中,我们使用fopen,fclose,fread,fwrite对文件进行相应的操作。由于操作系统内核的不同,在linux系统下,我们不仅仅可以使用C库里边的那些函数,还使用open,close,read,write对文件进行相应的操作,这些都是系统调用的函数。它们之间有联系也有区别,现在我们分析一下吧。

C库:

(1)FILE *fopen(const char *path, const char *mode);

(2)int fclose(FILE *fp);

(3)size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

(4)size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

系统调用:

(1)

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);        //flags表示打开的方式,主要有O_RDONLY,O_WRONLY,O_CREAT,O_EXCL等
int creat(const char *pathname, mode_t mode); //如果打开不成功的话,就自己创建一个

我们看出,使用open函数的时候,调用的是系统的函数,而上述fopen是使用C库里边的函数。还有一点是open的返回值是整形,这也是与fopen不一样的。我们使用fopen的时候,它是返回一个file*,在这里,open的返回值是整形,它代表文件描述符。即唯一标识打开文件的信息。文件描述符是什么呢。我们之前在task_struct中介绍过PCB的基本信息。简单了解了PCB结构体中的信息后,我们发现在task_struct结构体中有一个files_struct结构体就是用于存放打开文件的一系列信息。

struct files_struct {/** read mostly part*/atomic_t count;   //自动增量  bool resize_in_progress;wait_queue_head_t resize_wait;struct fdtable __rcu *fdt;  struct fdtable fdtab;   //文件描述符表/** written part on a separate cache line in SMP*/spinlock_t file_lock ____cacheline_aligned_in_smp;unsigned int next_fd;  //下一个文件描述符unsigned long close_on_exec_init[1]; //执行exec时
需要关闭的文件描述符初值集合  unsigned long open_fds_init[1]; //当前打开文件
的文件描述符屏蔽字  unsigned long full_fds_bits_init[1];struct file __rcu * fd_array[NR_OPEN_DEFAULT]; //指向文件描述符组的指针
};

FILE的结构
struct _iobuf {char *_ptr;          //缓冲区当前指针int   _cnt;char *_base;         //缓冲区基址int   _flag;         //文件读写模式int   _file;         //文件描述符int   _charbuf;      //缓冲区剩余自己个数int   _bufsiz;       //缓冲区大小char *_tmpfname;};
typedef struct _iobuf FILE;

可以看到,files_struct中有一个文件描述符表,用来存放文件描述符。我们对于程序启动时默认会打开三个文件:stdin,stdout,stderr,它们的文件描述符分别表示:0,1,2。头文件unistd.h中有如下宏:

#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2

总结一下:

每个进程在linux内核中都有一个描述进程信息的结构体,称为task_struct。而描述进程的信息称为PCB,每个进程都有自己的PCB(进程控制块)。在task_struct结构体中,有一个指向files_struct的结构体指针,files_struct结构体中,描述了相应的文件描述符,I/O缓冲区,下一个文件描述符等。

说起库函数和系统调用,我们知道,最底层是硬件->驱动程序->操作系统->系统调用->shell外壳程序->库函数->用户程序;所以可以知道,库函数是在系统调用的基础上形成的,因此也知道open与fopen的关系了吧,fopen的底层也是调用了open的。

这里写图片描述

同理,看一下另外的read,write,close

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);

使用这些函数的时候,参数传入文件描述符来确定是哪个文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/382726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[linux]wait详解

wait&#xff1a;进程等待 主要有两种等待方式&#xff1a;阻塞式等待和非阻塞式等待 阻塞式等待&#xff1a;如果子进程正在运行&#xff0c;父进程将会一直等待着子进程运行结束&#xff0c;并且自己什么事都不干 非阻塞式等待&#xff1a;如果子进程正在运行&#xff0c;…

[Linux]消息队列

我们知道进程间通信的方法有多种&#xff0c;主要有管道&#xff0c;消息队列&#xff0c;信号量&#xff0c;共享内存&#xff0c;socket等。之前介绍过管道&#xff0c;今天再介绍一个新的概念–消息队列。 消息队列&#xff1a;将一个进程到另一个进程之间发送数据块的方式…

C++关键字速查手册

[TOC] https://blog.csdn.net/csdn_kou/article/details/81113215 C98关键字 C11 关键字共73个 alignas alignof用于获取取指定表达式指定的&#xff08;类似sizeof&#xff0c;可以直接是类型名&#xff09;的对齐(alignment)。alignas用于声明时指定对齐类似于现有的类型…

[Linux]信号

Linux下的信号是一个什么概念呢。我们在现实生活中也遇到过信号之类的。比如红绿信号灯&#xff0c;班主任叫你去办公室并且脸色不好&#xff0c;诸如此类的都会给你一个信号。让你辨别事情的发生。同样&#xff0c;Linux下也有许多的信号&#xff0c;让你执行相应的操作。比如…

[数据结构]Map和Set

说起map和set&#xff0c;想必我们都学过红黑树了吧&#xff0c;map和set就是红黑树的一个应用领域。它的底层就是由红黑树来实现的。下面简单说一下map和set的使用吧。 首先&#xff0c;有一个栗子是这样的&#xff0c;让我们统计出每种水果出现的次数。 我们会想到怎么解决…

linux之信号

信号&#xff1a;在生活中&#xff0c;我们遇到过不同种类的信号&#xff0c;比如&#xff1a;&#xff08;交通信号&#xff0c;乃至某个人的表情&#xff0c;动作等带给你不同的信号&#xff09;然而&#xff0c;在我们的linux下&#xff0c;我们最熟悉的就是&#xff0c;当遇…

[Linux]继续探究mysleep函数(竞态条件)

之前我们探究过mysleep的简单用法&#xff0c;我们实现的代码是这样的&#xff1a; #include<stdio.h> #include<signal.h>void myhandler(int sig) {}unsigned int mysleep(unsigned int timeout) {struct sigaction act,oact;act.sa_handler myhandler;sigempt…

[Linux]死锁

死锁是指多个进程在运行过程中因争夺资源而造成的一种僵局&#xff0c;当进程处于这种僵持状态时&#xff0c;若无外力作用&#xff0c;它们都将无法再向前推进。之前信号量的时候我们知道&#xff0c;如果多个进程等待&#xff0c;主要体现在占有锁的问题上。死锁也可以被定义…

[Linux]线程安全和可重入函数

线程安全&#xff1a;一个函数被称为线程安全的&#xff0c;当且仅当被多个并发进程反复调用时&#xff0c;它会一直产生正确的结果。如果一个函数不是线程安全的&#xff0c;我们就说它是线程不安全的。 重入&#xff1a;函数被不同的控制流程调用,有可能在第一次调用还没返回…

[Linux]信号量

信号量是一个计数器&#xff0c;用于为多个进程提供对共享数据对象的访问。 在信号量上只有三种操作可以进行&#xff0c;初始化、递增和增加&#xff0c;这三种操作都是原子操作。递减操作可以用于阻塞一个进程&#xff0c;增加操作用于解除阻塞一个进程。 为了获得共享资源…

[Linux]关于SIGCHLD

之前我们就学过&#xff0c;关于wait和waitpid来处理僵尸进程&#xff0c;父进程等待子进程结束后自己才退出&#xff0c;这样的方法有俩种方式&#xff0c;一种是父进程死死的等子进程退出&#xff0c;也就是使用阻塞的方式等待子进程退出&#xff0c;另一种方式是通过非阻塞的…

C语言思维导图

本人能力有限&#xff0c;知识点难免概括不全&#xff0c;如有错误欢迎指正

pthread和互斥量条件变量函数意义速查表

数据类型 pthread_t 线程 互斥量和条件变量

[Linux]共享内存

共享内存是UNIX提供的进程间通信手段中速度最快的一种&#xff0c;也是最快的IPC形式。为什么是最快的呢&#xff0c;因为数据不需要在客户进程和服务器进程之间复制&#xff0c;所以是最快的一种IPC。这是虚存中由多个进程共享的一个公共内存块。 两个不同进程A、B共享内存的…

[Linux]gdb调试多进程多线程例程

gdb相信学linux的同学已经比较熟悉了吧&#xff0c;它是linux下代码调试工具。我们在写c语言&#xff0c;c的代码时经常会用到&#xff0c;它有一些常用的调试命令: run&#xff08;r&#xff09;&#xff1a;运行程序&#xff0c;如果有断点在下一个断点处停止 start&#xf…

[Linux]守护进程(精灵进程)

一、守护进程是什么 守护进程是生存期很长的一种进程&#xff0c;可以说它是7*24小时工作的。&#xff08;什么是7*24&#xff0c;一周7天&#xff0c;每天24小时&#xff0c;这不就是一年365天一直在工作嘛&#xff0c;还搞的这么诙谐&#xff0c;哈哈&#xff09;。它们常常…

浅谈shell中的clear命令实现

NAME(名称) clear - 清除终端屏幕 SYNOPSIS(总览) clear DESCRIPTION(描述) clear可以在允许的情况下清屏. 它会在环境变量中查找终端的类型, 然后到terminfo数据库中找出清屏的方法. 《man手册》 #include <stdio.h>int clear_main(int argc, char **argv) {/* Th…

[Linux]ARP协议

概念&#xff1a; 1. ARP协议(地址解析协议):由IP地址转换为MAC地址的协议。IP地址&#xff1a;网络号主机号。MAC地址&#xff1a;数据链路层的物理地址&#xff08;硬件地址&#xff09;。IP协议使用了ARP协议&#xff0c;因此被划归为网络层&#xff0c;但其用途是从网络层…

Makefile使用及多文件gdb 调试

文件内容 [koulocalhost makefile]$ cat 1.c #include "3.h" int main() {key_t key ftok(".",1);printf("%d\n",add(1,2));return 0; }[koulocalhost makefile]$ cat 2.c #include "3.h" int add(int a, int b) {return a b; } [k…

[Linux]CRC校验

CRC(Cyclic Redundancy Check),循环冗余校验码&#xff0c;是数据通信领域中最常用的一种差错校验码&#xff0c;其特征是信息字段和校验字段的长度可以任意选定。 CRC校验步骤&#xff1a; CRC分为两部分&#xff0c;前部分为信息码&#xff0c;后部分为校验码&#xff1b;设…