Linux李哥私房菜——open、close和fd

open()

头文件:#include<fcntl.h>//在centos6.0中只要此头文件就可以
       #include<sys/types.h>
       #incldue<sys/stat.h>
功能:打开和创建文件(建立一个文件描述符,其他的函数可以通过文
     件描述符对指定文件进行读取与写入的操作。)

文件描述符号fd详解:

  1. 概述
    在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误,POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号码,因此,在网络通信过程中稍不注意就有可能造成串话,所以,如果此时去打开一个新的文件,它的文件描述符会是3(标准输入输出错误也是文件,提前把前三个坑抢了)。标准文件描述符图如下:
    在这里插入图片描述

总结:

fd定义:每一个进程在内核中,会有一个“打开文件”表数组,每一个元素都指向一个内核的打开文件对象,而fd就是数组的下标,我们对文件进行操作时,系统调用,将fd传入内核,内核通过fd找到文件,对文件进行操作,
虽然只是下标,但是内核根据下标操作文件,所以fd用于指代被打开的文件,由于这个表处于内核,并且用户无法访问到,因此用户即使拥有fd,也无法得到打开文件对象的地址,只能够通过系统提供的函数来操作(比如write和read)。

既然是数组下标,fd的类型为int, < 0 为非法值, >=0 为合法值。在linux中,一个进程默认可以打开的文件数为1024个,fd的范围为0~1023。可以通过设置,改变最大值。

通常在程序中打开的fd,是从3开始的。我们在判断一个fd是否合法时,依然要使用>=0的判断标准

内核对所有打开的文件的文件维护有一个系统级的描述符表格(open file description table)。有时,也称之为打开文件表(open file table),并将表格中各条目称为打开文件句柄(open file handle)。一个打开文件句柄存储了与一个打开文件相关的全部信息,如下所示:
1. 当前文件偏移量(调用read()和write()时更新,或使用lseek()直接修改)
2. 打开文件时所使用的状态标识(即,open()的flags参数)
3. 文件访问模式(如调用open()时所设置的只读模式、只写模式或读写模式)
4. 与信号驱动相关的设置
5. 对该文件i-node对象的引用
6. 文件类型(例如:常规文件、套接字或FIFO)和访问权限
7. 一个指针,指向该文件所持有的锁列表
8. 文件的各种属性,包括文件大小以及与不同类型操作相关的时间戳
下图展示了文件描述符、打开的文件句柄以及i-node之间的关系,图中,两个进程拥有诸多打开的文件描述符。

这里是引用

int open(const char*pathname,int flags);
int open(const char*pathname,int flags,mode_t mode);
参数说明:
1.pathname
  要打开或创建的目标文件
2.flags
  打开文件时,可以传入多个参数选项,用下面的
  一个或者多个常量进行“或”运算,构成falgs
  参数:
  O_RDONLY:   只读打开
  O_WRONLY:   只写打开
  O_RDWR:     读,写打开
这三个常量,必须制定一个且只能指定一个
  O_CREAT:    若文件不存在,则创建它,需要使
              用mode选项。来指明新文件的访问权限
  O_APPEND:   追加写,如果文件已经有内容,这次打开文件所
              写的数据附加到文件的末尾而不覆盖原来的内容


返回值

成功:新打开的文件描述符
失败:-1
open返回的文件描述符一定是最小的而且没有被使用的

fopen与open的区别

以可写的方式fopen一个文件时,如果文件不存在则会自动创建,而open一个文件时必须明确O_CREAT才会创建文件,否则文件不存在就出错返回

close

头文件:#include<unistd.h>
功能:关闭一个已经打开的文件

原型

int close(int fd)
参数说明:
fd:是需要关闭的文件描述符

返回值

成功:返回0;
失败:返回-1,并设置errno

打开的文件描述符一定要记得关闭,否则资源会被大量的占用,导致内存不够

open打开的文件存在时:
示例:
1.
代码:

#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
 int fd=open("myfile",O_WRONLY);
 if(fd<0)
 {
  perror("open");
  exit(1);
 }
 const char*msg="hello open\n";
 int count = 6;
 while(count--)
 {
  write(fd,msg,strlen(msg));
 }
 close(fd);
 return 0;
}

运行结果:
在这里插入图片描述
2.
代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
int main()
{
 int fd=open("myfile",O_RDWR);
 if(fd<0)
 {
  perror("open");
  exit(1);
 }
 const char*msg="hello  hahaha\n";
 int count= 10;
 while(count--)
 {
 write(fd,msg,strlen(msg));
 }
 char buf[1024]={0};
 int num=10;
 while(num--)
 {
 read(fd,buf,strlen(msg));
 }
 close(fd);
 return 0;
}

运行结果:
这里写图片描述
open打开的文件不存在时:

代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
int main()
{
 int fd=open("file",O_WRONLY|O_CREAT,0644);
 //file文件不存在,所以在书写第二个参数时,记得把O_CREAT加上,
 //如果不加O_CREAT的话,程序就会报此文件不存在
 if(fd<0)
 {
  perror("open");
  exit(1);
 }
 const char*msg="hello file\n";
 int count=10;
 while(count--)
 {
  write(fd,msg,strlen(msg));
 }
 close(fd);
 return 0;
}

运行结果:
在这里插入图片描述

总结:

open函数会返回一个fd,fd是一个整数类型的数组下标,,系统函数可以通过fd可以对文件进行操作。这个数组中的指针指向打开文件表,表中的每一行都描述了一个文件的属性,包括文件偏移量,i-node指针和打开模式。文件偏移量会根据write和read时更新(read和write函数成功调用时会返回这一次调用所读写的字节长度)。

参考:
https://blog.csdn.net/sybnfkn040601/article/details/73718332?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

https://blog.csdn.net/dangzhangjing97/article/details/79631173

他们都告诉你,必须要做什么,却没告诉你为什么。
##《 欢迎访问我的网站,ai工具箱https://4398ai.com里面有免费的chatgpt网站,和很多免费的编程资源的干货》
在这里插入图片描述

### 考研图片分类资料概述 关于考研中的图片分类相关内容,可以从其涉及的深度学习基础理论以及具体实现细节入手。以下是针对该主题的一些核心知识点及其解释。 #### 特征图计算与卷积核大小 在图片分类过程中,卷积操作是非常重要的一步。假设有一个 $3 \times 4 \times 4$ 的输入特征图,在应用 `padding=1` 单个卷积核的情况下,如果最终得到的是一个 $1 \times 4 \times 4$ 的特征图,则可以通过以下方式推导出卷积核的尺寸[^3]: - 输入维度为 $3 \times 4 \times 4$ - 输出维度为 $1 \times 4 \times 4$ 由于输出的高度宽度保持不变(即仍为 $4 \times 4$),这意味着卷积核的步幅(stride)应设置为 1,并且通过填充(padding=1)使得边界像素得以保留。因此,卷积核的大小应该是 $3 \times 3$,其中高度宽度均为 3,通道数等于输入特征图的深度(即 3)。 此外,对于这样一个卷积核而言,它的总参数量可由公式 $(\text{kernel height} \times \text{kernel width} \times \text{input channels}) + 1$ 计算得出,这里加上的 “1” 是偏置项。代入数值后得:$(3 \times 3 \times 3) + 1 = 28$ 参数。 #### 数据集构建方法 在实际训练之前,通常需要将多个批次的数据合并起来形成完整的训练集合测试集。例如,给定一批次数据 $\{(x_0, y_0), (x_1, y_1)\}$ ,可以按照如下方式进行处理[^2]: ```python import numpy as np def concatenate_batches(X_list, Y_list): X_all = [] Y_all = [] for i in range(len(X_list)): if i == 0: X_all = X_list[i] Y_all = Y_list[i] else: X_all = np.concatenate((X_all, X_list[i]), axis=0) Y_all = np.concatenate((Y_all, Y_list[i]), axis=0) return X_all, Y_all ``` 此函数接受两个列表作为输入——分别存储各批次样本矩阵 (`X_list`) 及标签向量(`Y_list`) 。随后利用 NumPy 库提供的 `concatenate()` 函数沿着第一个轴方向依次连接各个数组片段,从而完成整个数据集组装工作。 #### 模型架构设计思路 考虑到复杂度较高的图像分类任务时,往往采用深层神经网络结构来提取更加抽象有效的特征表达形式。以 ResNet50 或者 VGG16 这样的经典预训练模型为基础框架进行微调是一种常见做法[^1]: ```python from tensorflow.keras.applications import resnet50 from tensorflow.keras.models import Model from tensorflow.keras.layers import Dense, GlobalAveragePooling2D base_model = resnet50.ResNet50(weights='imagenet', include_top=False) x = base_model.output x = GlobalAveragePooling2D()(x) predictions = Dense(num_classes, activation='softmax')(x) model = Model(inputs=base_model.input, outputs=predictions) for layer in base_model.layers: layer.trainable = False model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) ``` 上述代码展示了如何基于 Keras API 构建并编译一个用于解决多类别图像分类问题的新模型实例。值得注意的是,在初始阶段冻结了原始基底模型内的所有权重更新权限,仅允许新增全连接层参与反向传播过程的学习调整活动;待初步收敛后再逐步解冻部分底层卷积模块重新优化整体性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值