二、系统IO

本文详细介绍了C语言中sysio库的文件I/O操作,包括open(), close(), read(), write(), lseek(), dup(), dup2(), fileno()等,并通过原子操作的实例提升实践能力。重点讲解了文件描述符的管理策略和常见文件操作技巧。

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

二、(sysio)文件IO

文件描述符使用策略:优先使用最小的

1、open()

函数功能:使用给定的模式flags打开pathname所指定的文件

函数原型:( $: man 2 open --> 手册 )

  • 当文件存在时

    int open(const char* pathname,int flags)  //
    //只要有open就会产生一个结构体,然后去调用它,返回给用户一个整型数文件描述符。
    //拿到的是一个文件描述符,然后通过描述符引用结构体。
    
  • 当文件不存在时(flag --> O_CREAT)

    int open (const char *pathname, int flags, mode_t mode)
    //返回值:成功 --> 文件描述符  失败 --> -1
    //文件描述符使用策略:优先使用当前可用范围内最小的id
    

参数:

            ┌─────────────┬───────────────────────────────┐
            │fopen() mode │ open() flags                  │
            ├─────────────┼───────────────────────────────┤
            │     r       │ O_RDONLY                      │
            ├─────────────┼───────────────────────────────┤
            │     w       │ O_WRONLY | O_CREAT | O_TRUNC  │
            ├─────────────┼───────────────────────────────┤
            │     a       │ O_WRONLY | O_CREAT | O_APPEND │
            ├─────────────┼───────────────────────────────┤
            │     r+      │ O_RDWR                        │
            ├─────────────┼───────────────────────────────┤
            │     w+      │ O_RDWR | O_CREAT | O_TRUNC    │
            ├─────────────┼───────────────────────────────┤
            │     a+      │ O_RDWR | O_CREAT | O_APPEND   │
            └─────────────┴───────────────────────────────┘

flags含义
O_RDONLY只读
O_WRONLY只写
O_CREAT无则创建
O_TRUNC有则清空
O_APPEND追加
O_RDWR可读可写

2、close()

int close(int fd)
//返回值:成功:0  失败:-1

3、read()

函数功能:从fd所指向的文件中读count个字节到buff缓存区

ssize_t read(int fd,void *buff,size_t count)
//<unistd.h>

返回值

成功:

  • count:成功读取全部字节
  • 0~count:
    • 剩余文件长度小于count
    • 读取期间被异步信号打断

失败:

  • -1,读取错误

4、write()

函数功能:从fd所指向的文件中写入count个字节到buff缓存区

ssize_t write(int fd,void *buff,size_t count)
//<unistd.h>

返回值

成功:

  • count:成功写入全部字节
  • 0~count:
    • 写入期间被异步信号打断

失败:

  • -1,读取错误

函数测试:实现文件拷贝

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define BUFSIZE 1024

int main(int argc,char *argv[])
{
	int sfd,dfd;
	char buf[BUFSIZE];
	ssize_t len,ret,pos;

	if(argc < 3)
	{
		fprintf(stderr,"Usage:%s srcfile destfile\n",argv[0]);
		exit(1);
	}

	sfd = open(argv[1],O_RDONLY);
	if(sfd < 0)
	{
		perror("open()");
		exit(1);
	}

	dfd = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600); //只写有则清空无则创建
	if(dfd < 0)
	{
		perror("fopen()");
		exit(1);
	}

	while(1)
	{
		len = read(sfd,buf,BUFSIZE);  //每次循环成功拷贝len个字节
		if(len == 0)
			break;
		if(len < 0)
		{
			perror("read()");
			exit(1);
		}

		//len > 0
		pos = 0;
		while(len > 0)
		{
			ret = write(dfd,buf+pos,len);	
			if(ret < 0)
			{
				perror("write()");
				exit(1);
			}
			pos += ret;
			len -= ret;  
		}
	}

	close(dfd);
	close(sfd);

	exit(0);
}

5、lseek()

函数功能:设置文件读写位置

off_t lseek(int fd,off_t offset,int whence)
//返回值:成功 --> 文件偏移位置值 失败 --> -1
  • 若whence为SEEK_SET,基准点为文件开头
  • 若whence为SEEK_CUR,基准点为当前位置
  • 若whence为SEEK_END,基准点为文件末尾

6、dup()

函数功能:复制文件描述符oldfd

int dup(int oldfd);   //oldfd已有的文件描述符

代码应用:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


int main()
{
	int fd;

	fd = open("/tmp/out",O_WRONLY|O_CREAT|O_TRUNC,0600);
	if(fd < 0)
	{
		perror("open()");
		exit(1);
	}

	close(1);
	dup(fd);

	close(fd);
//---------------------------------------------
	puts("Hello!");

	exit(0);
}

7、dup2()

函数功能:将一个描述符oldfd复制到newfd

int dup2(int oldfd, int newfd);

代码应用:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
	int fd;

	fd = open("/tmp/out",O_WRONLY|O_CREAT|O_TRUNC,0600);
	if(fd < 0)
	{
		perror("open()");
		exit(1);
	}
	dup2(fd,1);

	if(fd != 1)
		close(fd);
//---------------------------------------------
	puts("Hello!");

	exit(0);
}

8、fileno()

int fileno(FILE *stream);
//The function clearerr() clears the end-of-file and error indicators for
//the stream pointed to by stream.

复制普通文件小实验

1、打开要复制的文件

2、创建新的文件

3、把源文件内容读到缓冲区,把缓冲区内容写入新文件

4、循坏执行第三步,直到读取的字节数量为0,退出循坏。

5、关闭打开的文件

拓展提升:

1、原子操作(3.11)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值