Linux下系统调用和标准IO库介绍

系统调用概述

系统调用是操作系统提供给用户程序的一组“特殊”接口。程序可以通过这些接口向内核请求服务。这些接口被称为系统调用。
系统调用按照功能逻辑大致可分为: 进程控制、进程间通信、文件系统控制、系统控制、内存管理、网络管理、socket控制、用户管理。

系统调用I/O函数

系统调用中操作I/O的函数,都是针对文件描述符的。通过文件描述符可以直接对相应的文件进行操作。如:open、close、write 、read、ioctl
文件描述符是非负整数。打开现存文件或新建文件时,系统(内核)会返回一个文件描述符。文件描述符用来指定已打开的文件。
默认打开的三个文件描述符:
#define STDIN_FILENO 0 //标准输入的文件描述符
#define STDOUT_FILENO 1 //标准输出的文件描述符
#define STDERR_FILENO 2 //标准错误的文件描述符
open函数:打开一个文件

#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);
参数:
pathname:文件的路径及文件名。 
flags:open函数的行为标志。 
mode:文件权限(可读、可写、可执行)的设置。 
返回值: 
成功返回打开的文件描述符。 
失败返回-1,可以利用perror去查看原因
flag取值意义
O_RDONLY以只读的方式打开
O_WRONLY以只写的方式打开
O_RDWR以可读、可写的方式打开
O_CREAT文件不存在则创建文件,使用此选项时需使用mode说明文件的权限
O_EXCL如果同时指定了O_CREAT,且文件已经存在,则出错
O_TRUNC如果文件存在,且为只读或只写的方式打开,则清空文件内容
O_APPEND写文件时,数据添加到文件末尾
O_NONBLOCK当打开的文件是FIFO、字符文件、块文件时,此选项为阻塞标志位

close函数:关闭一个文件

#include <unistd.h> 
int close(int fd); 
参数: 
fd是调用open打开文件返回的文件描述符 
返回值: 
成功返回0。 
失败返回-1,可以利用perror去查看原因

write函数:把指定数目的数据写到文件

#include <unistd.h> 
ssize_t write(int fd, const void *addr, size_t count); 
参数: 
fd:文件描述符。 
addr:数据首地址。 
count:写入数据的字节个数。 
返回值: 
成功返回实际写入数据的字节个数。 
失败返回-1,可以利用perror去查看原因。	

read函数:把指定数目的数据读到内存

#include <unistd.h> 
ssize_t read(int fd, void *addr, size_t count);
参数: 
fd:文件描述符。 
addr:内存首地址。 
count:读取的字节个数。 
返回值: 
成功返回实际读取到的字节个数。 
失败返回-1,可以利用perror去查看原因

库函数

库函数一般是指编译器提供的可在c源程序中调用的函数。
库函数与系统调用的关系:
并不是所有的系统调用都被封装成了库函数,系统提供的很多功能都必须通过系统调用才能实现。

系统调用函数与库函数各自有什么优缺点?
系统调用优点:
​ ​1、当要处理的数据量比较大时,例如当输入输出的数据量超过文件系统定义的尽寸时,利用系统调用可获得较高的效率。
​ ​ 2、 从程序执行效率来看,系统调用的执行效率大多要比函数高,尤其是处理输入输出的函数。
3、用于内核空间的驱动程序中对设备的操作

系统调用缺点:
​ ​1、系统调用是使用时间的,频繁进行系统调用会降低程序运行效率
2、移植性差
库函数优点
​ ​1、设置不同类型缓冲区,减少之间调用IO调用的次数,提高了访问效率
​ ​2、可移植性好
​库函数缺点
​ ​1、不可能用于内核空间的驱动程序中对设备的操作
2、一般情况下,执行效率不如系统调用

标准I/O库函数

打开流

#include <stdio.h>
FILE* fopen(const char *pathname,
const char *mode);
函数说明:
pathname: 文件的路径及文件名。
mode: 流的打开方式。
返回值:
成功:返回指向该流的指针。
失败:则返回NULL,并把错误代码存在errno中

关闭流

#include <stdio.h>

int fclose(FILE *stream);
函数说明:
fclose用来关闭fopen打开的文件。此动作会让缓	冲区的数据写入文件中,并释放系统所提供的文件资源。
返回值:
成功返回0;失败返回EOF,并把错误代码存到errno中

读、写流
每次读、写一个字符

int getchar(void);
int getc(FILE *stream);
int fgetc(FILE *stream);
int putchar(int c);
int putc(int c, FILE *stream);
int fputc(int c, FILE *stream);

每次读、写一行字符

char *gets(char *buf);
char *fgets(char *buf, int n, FILE *stream);
fgets从stream指定的文件中最多读取n-1个字符 放到buf所指向的数组中。读到换行符或文件结束符后 不再向后读,最后一个字符读入后接着写入一个空字符。
返回值:
成功返回buf;失败返回NULL
注意:
gets()丢掉输入里的换行符。
fgets()存储输入中的换行符

每次一个数据块

size_t fread(void *ptr, size_t size,size_t nobj, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *stream);
size是数据块大小,nobj指要读取或写入的数据块个数,stream指定要操作的数据流。
注意:
两个函数返回的是实际读或写的数据的个数,而不是整个数据的字节数。

示例题目

使用系统调用函数编程,实现文件的复制(类似Linux命令cp),例如生成的可执行程序为app,运行程序时:./app a.txt b.txt
将a.txt文件内容复制到b.txt文件中

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char **argv)
{
	int fd1,fd2,count=0;
	char buf[512];
	if(argc < 3)
	{
		printf("please input ./app test1 test2");
	}
	fd1 = open(argv[1],O_RDONLY,0755);
	if(fd1 < 0)
	{
		printf("error");
		return -1;
	}
	fd2 = open(argv[2],O_RDWR|O_CREAT,0755);
	if(fd2 < 0)
	{
		printf("error");
		return -1;
	}
	while((count = read(fd1,buf,100))>0)
	{
		write(fd2,buf,count);

	}
	close(fd1);
	close(fd2);
	return  0;

}

使用库函数方法,实现上面的功能

#include <stdio.h>
int main(int argc,char **argv)
{
	
	char *buf[1024] = {0};
	if(argc < 3)
	{
		printf("please input ./app test1 test2");
		return -1;
	}
	FILE *file1 = fopen(argv[1],"r");
	if(file1 == NULL)
	{
		printf("error");
		return -1;
	}
	FILE *file2 = fopen(argv[2],"w");
	if(file2 == NULL)
	{
		printf("error");
		return -1;
	}
	while(!(feof(file1)))
	{
		int count = fread(buf,sizeof(void),1024,file1);
		if(ferror(file1))
		{
			perror("file1");
			fclose(file1);
			fclose(file2);
			return -4;

		}
		int count2 = fwrite(buf,sizeof(void),count,file2);
		if(count2 == 0)
		{
			perror("file2");
			fclose(file1);
			fclose(file2);
			return -5;

		}
		

	}
	fclose(file1);
	fclose(file2);
	return 0;




}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_17616

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值