linux系统的文件I/O

本文介绍了Linux中文件类型、文件描述符的使用,系统调用的概念,以及关键的I/O操作函数如open、read、write和lseek。通过实例展示了如何处理普通文件、目录、链接等不同类型,并演示了如何使用这些函数进行文件操作和定位读写位置。

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

一.文件描述符及文件处理

1.文件及文件描述符

linux下的设备和文件都可以看作文件,linux中有七种文件类型:普通文件,目录文件,链接文件,块设备文件,字符设备文件,套接字文件,管道文件。

普通文件:包含纯文本文件(ASCII,Unicode等编码文件),二进制文件(可执行文件,压缩文件等)

目录文件:记录目录的文件

链接文件:与windows下的快捷方式文件类似

块设备文件:可存储数据的外部设备,包括硬盘等存储设备

字符设备文件:即串行端口的接口设备,例如键盘、鼠标等。

套接字文件:这类文件通常用在网络数据连接。

管道文件:管道文件是一种很特殊的文件,主要用于不同进程的信息传递。

文件类型标识文件类型
-普通文件
d目录
l符号链接
s套接字
b块设备
c字符设备
p管道

 

 

 

 

 

 

 

linux使用文件描述符来操作特定的文件,文件描述符是一个非负整数。通常一个进程启动时会打开三个文件:标准输入,标准输出,标准错误,它们的文件描述符分别是0,1,2。

2.系统调用

   linux为了更好的保护内核空间,将程序运行空间分为内核空间和用户空间,它们运行在不同的级别上,逻辑上相互隔离,因此,用户程序通常不能直接访问内核数据。但是,某些情况下用户需要获得一定的系统服务,因此,操作系统需要向用户提供“特殊接口”---系统调用,进行系统调用时,程序从用户态进入内核态,处理完后返回用户态。

3.文件处理

  linux系统调用和C/C++标准函数库都能处理文件,不同的是,C/C++标准函数库的I/O操作是基于系统调用实现的,它们是独立于操作系统的,不同的系统上其内部实现不同。

二.I/O操作的相关函数

1.open函数

open函数用于打开或创建文件,调用open函数需要包含的头文件:

#include<stdio.h>

#include<fcntl.h>

其函数原型为:

int  open(const char *pathname, int flag, int perms);//打开成功则返回文件描述符,出错则返回-1

pathname:要打开或创建的文件名,可包含路径。

flag:函数功能选项,供选择参数有:

       O_RDONLY:以只读方式打开文件。

       O_WRONLY:以只写方式打开文件。

       O_RDWR:以读写方式打开文件。

以上参数只能指定一个,其他可选参数:

      O_APPEND:每次写时写入文件末尾。

      O_CREAT:文件不存在则创建,使用此选项需要指定perms的值。

      O_TRUNC:如果文件存在且以只读或只写打开,则会先全部删除文件原来的数据。

perms:可选参数,指定新建文件的存取权限,采用八进制表示。

测试代码:

#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#define FILEA "a.txt"
#define FILEB "b.txt"
#define FILEC "c.txt"

int main(void)
{
  int fd_a,fd_b,fd_c;
  fd_a=open(FILEA,O_RDONLY);
  if(fd_a==-1)
  {
	  printf("open %s failed!\n",FILEA);
	  printf("fd_a=%d\n",fd_a);
  }
  else
  {
	  printf("open %s successed!\n",FILEA);
	  printf("fd_a=%d\n",fd_a);
  }

  fd_b=open(FILEB,O_RDWR);
  if(fd_b==-1)
  {
      printf("open %s failed!\n",FILEB);
	  printf("fd_b=%d\n",fd_b);
  }
  else
  {
	  printf("open %s successed!\n",FILEB);
	  printf("fd_b=%d\n",fd_b);
  }

  fd_c=open(FILEC,O_RDWR|O_CREAT|O_TRUNC,0666);
  if(fd_c==-1)
  {
	  printf("open %s failed!\n",FILEC);
	  printf("fd_c=%d\n",fd_c);
  }
  else
  {
          printf("open %s sucessed!\n",FILEC);
	  printf("fd_c=%d\n",fd_c);
  }
  if(fd_a!=-1)
           close(fd_a);
   if(fd_b!=-1)
	   close(fd_b);
   if(fd_c!=-1)
	   close(fd_c);

  return 0;
}

测试结果:

由于a.txt不存在,所以a.txt打开失败,文件描述符为-1;b.txt存在,返回文件描述符为3;新建了c.txt文件,返回文件描述符为4。返回的文件描述符总是在进程中当前没有打开的最小描述符。

2.read函数

read函数从打开断地文件中读取数据,read函数原型为:

ssize_t  read(int fd,  void *buf,   size_t count);//返回实际读取到的字节数,若返回0则已到达文件尾部,若返回-1则出错。

fd:文件描述符

buf:读取数据缓冲区

count:指定的读取字节数

测试代码:

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>

#define max_size 5

int main(void)
{
	int fd,count;
	char buf[max_size+1];
	fd=open("test.txt",O_RDONLY);
	if(fd==-1)
	{
		printf("test.txt not exist!\n");
		return -1;
	}
        count=read(fd,buf,max_size);
	if(count>0)
	{
		buf[count]='\0';
		printf("content of test.txt:%s\n",buf);
	}
	else
	{
		printf("read test.txt failed!\n");
	}
	close(fd);

	return 0;
}

测试结果:

3.write函数

write函数用于向打开的文件写入数据。write函数原型为:

ssize_t write(int fd,  void *buf,  size_t count);//返回实际写入的数据字节数,若出错则返回-1

fd:文件描述符

buf:待写入数据缓冲区

count:指定的写入字节数

测试代码:

#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>

int main(void)
{
  int fd,count;
  char buf[]="hello,world!";
  fd=open("a.txt",O_RDWR|O_CREAT,0666);
  if(fd==-1)
  {
	  printf("failed to open a.txt!\n");
	  return -1;
  }
  count=write(fd,buf,sizeof(buf));
  if(count<0)
  {
	  printf("failed to write buf to a.txt!\n");
          close(fd);
	  return -1;
  }
  else
  {
	  printf("write %d bytes to a.txt!\n",count);
  }
  close(fd);


  return 0;
}

测试结果:

4.lseek函数

lseek函数用于将文件指针定位到相应位置以进行读写操作,lseek的函数原型:

off_t   lseek(int  fd,  off_t  offset,  int whence);//返回文件的当前位移,若返回-1则出错。

fd:文件描述符

offset:偏移量,可正可负

whence:参考的位置基点,有3种参数:

            SEEK_SET:以文件开头作为偏移的基点

            SEEK_CUR:以当前指针位置作为偏移的基点

            SEEK_END:以文件尾部作为偏移的基点

测试代码:

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>

#define max_size 5

int main(void)
{
	int fd,count;
	char buf[max_size+1];
	fd=open("test.txt",O_RDONLY);
	if(fd==-1)
	{
		printf("test.txt not exist!\n");
		return -1;
	}
	lseek(fd,5,SEEK_SET);
        count=read(fd,buf,max_size);
	if(count>0)
	{
		buf[count]='\0';
		printf("content of test.txt:%s\n",buf);
	}
	else
	{
		printf("read test.txt failed!\n");
	}
	close(fd);

	return 0;
}

测试结果:

可以看到,读取的数据跳过了前5个数字,这正是预期的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值