【Linux】Linux下文件操作函数

本文对比了C语言中的库函数和Linux的系统调用函数,详细阐述了两者之间的区别和效率差异,并重点介绍了Linux下进行文件操作的系统调用函数,包括open、read、write、close、lseek等,还提到了通过这些函数实现文件拷贝的练习题,以及用户态到内核态的切换过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C语言中:fopen()        fread()     fwrite()        fclose()      fseek()   ——库函数

Linux:   open()           read()       write()        close()       lseek()        stat()         ——系统调用函数

1.库函数的系统调用函数的区别

系统调用函数是操作系统为内核代码提供给上层使用的函数接口,它的调用在用户态,可由应用程序调用,执行在内核态,由操作系统内核实现,有操作系统内核权限

库函数是语言自身带的库文件,其中是特定功能的实现,由编译器实现封装成的在用户态调用,在用户态执行,但有些库函数需要转调系统调用函数。

库函数不能直接去操纵物理硬件,必须经过操作系统,所以有些库函数要转调系统调用函数才可以(库函数中只要需要底层支持的都绕不开操作系统,绕不过操作系统就要调用系统调用函数)

所以printf和scanf需要底层支持(一个从界面获取数据,一个将数据打印到界面),而strlen和strcpy则不需要

2.二者效率

(1)库函数有时效率高于系统调用函数,原因:

a.系统调用函数的需要从用户态切换到内核态,而库函数则不需要切换

b.用库函数申请内存时,可能会多分配一些内存,但使用系统调用函数申请时,不会多分配,你申请多少他只会给你分配多少,这在你还需要更大一些内存的情况下,库函数效率高一些

(2)系统调用函数有时效率高于库函数,原因:

有些库函数的调用还需转调系统调用函数

3.Linux文件操作函数

 包含的头文件:

#include<sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

(1)int open(const char* filename,int flag,/*int mode*/)

返回值:<0 出错

                  >=0 正确,该值是文件描述符fd,打开的的文件标识 read write close lseek

参数解释:

filename:要打开的文件名(只给文件名就只会在当前路径下搜索)

flag:打开的方式 读O_RDONLY 写O_WRONLY 读写O_RDWR         追加O_APPEND

O_CREAT 创建(文件存在的话加这个选项没有意义,若文件不存在设置该参数时会创建一个新的文件,若文件不存在又没设置该参数,则打开失败报错,返回-1)

mode:只有在创建文件时指定文件的权限,nnnn,一般第一个n为0

(2)int read(int fd,void *buf,size_t size)

返回值:出错,返回-1

               成功,返回读到的数据字节数

参数解释:

fd:读取的文件由open的返回值指定

buf:指定读取的数据存储的起始位置

size:指定一次最多读取的字节数(一般情况下<=缓冲区的大小,缓冲区的大小-1,预留‘\0’的的位置,不能大于缓冲区大小,防止越界)

(3)int write(int fd,void *buf,size_t size)

返回值:出错,返回-1

               成功,返回已经写入成功的数据的长度(字节数)(正写时可能会出错)

参数解释:

fd:写入对象(open打开的灯文件)

buf:写入的数据的起始位置

size:写入数据的长度(字节),并不是buff空间的大小

char *buff[128]=”hello world”

write(fd,buff,strlen(buff));//长度是11

当写入时,文件不存在,O_WRONLY | O_CREAT

int fd=open(“./a.txt”,O_WRONLY | O_CREAT,0664);

(4)int close(int fd)关闭打开的文件

返回值:出错,返回-1

               成功,返回0

参数解释:

fd:指定文件描述符

(5)int lseek(int fd,int size int flag)     移动读写偏移量

返回值:出错,返回-1

              文件读写指针距文件开头的字节大小           

参数解释:

fd:操作的文件

size:移动的大小(字节)

flag:移动标记,移动的起始位置:SEEK_SET(文件开头)               SEEK_CUR(文件当前位置)         SEEK_END(文件结尾)

(6)stat获取文件的属性信息

#include <sys/stat.h>

int stat(const char *pathname, struct stat *buf);

int lstat(const char *pathname, struct stat *buf);

int fstat(int filedes, struct stat *buf);

函数功能:获取文件信息并保存在buf所指的结构体stat中。

一旦给出pathname, stat函数就返回与此命名文件有关的信息结构。lstat 函数类似于stat,但是当命名的文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。fstat函数获取已在描述符filedes上打开文件的有关信息。

第二个参数buf是指针,

struct stat { 
    dev_t         st_dev;       //文件的设备编号 
    ino_t         st_ino;       //节点 
    mode_t        st_mode;      //文件的类型和存取的权限 
    nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1 
    uid_t         st_uid;       //用户ID 
    gid_t         st_gid;       //组ID 
    dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号 
    off_t         st_size;      //文件字节数(文件大小) 
    unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小) 
    unsigned long st_blocks;    //块数 
    time_t        st_atime;     //最后一次访问时间 
    time_t        st_mtime;     //最后一次修改时间 
    time_t        st_ctime;     //最后一次改变时间(指属性) 
};

在Linux命令中,使用到stat()函数最多的可能是ls -1命令,用它可以获得有关一个文件的所有信息。

一个练习题,通过系统调用函数open,read等,完成文件的拷贝cp,代码:

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	int fdr=open("main.c",O_RDONLY);
	assert(fdr!=-1);

	int fdw=open("test.c",O_WRONLY | O_CREAT,0664);
	assert(fdw!=-1);
	char buff[128]={0};
	while(1)
	{
		char buuff[128]={0};
		int n=read(fdr,buff,127);
		if(n<=0)
		{
			break;
		}

		write(fdw,buff,n);
	}

	close(fdr);
	close(fdw);

}

三、以open函数为例,描述用户态到内核态的切换过程

描述:当在用户态调用open()的时候,首先会发生这三件事,

(1)保存程序上下文,当前程序的运行状态

(2)将函数对应的系统调用号保存到eax寄存器中

(3)触发0x80中断(系统调用专有中断),中断处理程序(内核中)

当触发了0x80中断,内核态的中断处理程序工作,在系统调用表中找到寄存器存放的系统调用号对应的函数,调用该函数,,此处调用的是sys_open(),在函数执行完成后返回时,用eax寄存器将返回值带回到用户态。这一过程完成。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值