Linux程序设计(9)第三章:文件操作(1)文件结构 系统调用/库函数 write read

Linux程序设计(9)第三章:文件操作(1)文件结构 系统调用/库函数 write read

  • 1. 第三章 文件操作
  • 2. linux 文件结构
  • 3. 三个重要的设备文件
    • 3.1 /dev/console
    • 3.2 /dev/tty
    • 3.3 /dev/null
  • 4. 系统调用和设备驱动程序
    • 4.1 系统调用
    • 4.2. 库函数
      • 4.2.1. 系统调用的缺点:
      • 4.2.2 库函数定义
      • 4.2.3. 系统函数和库函数的关系
  • 5. 三个文件描述符:
  • 6. write
    • 6.1 原型
    • 6.2. write 功能:
    • 6.3. 返回值:
    • 6.4. 代码:
  • 7. read
    • 7.1 原型
    • 7.2 read 功能
    • 7.3 返回值
    • 7.4. 代码:

1. 第三章 文件操作

本章主要讲解 linux 中的文件、目录及相关操作。
如创建,打开,读写和关闭文件,及如何处理目录。

2. linux 文件结构

linux 中,一切都是文件。
那就是,通常程序完全可以像使用文件那样使用磁盘文件,串行口,打印机和其他设备。
大多数情况下,你只需要使用5个基本函数 open,close,read,write 和 ioctl 。
对目录而言,通常上层的 opendir/readdir 接口来读取目录。

3. 三个重要的设备文件

linux中比较重要的设备文件有三个

3.1 /dev/console

这个设备代表的是系统控制台。
错误信息和诊断信息通畅会被发送到这个设备。

3.2 /dev/tty

如果一个进程有控制终端的话,那么特殊文件/dev/tty就是这个控制终端(键盘和显示器,或键盘和窗口)的别名。
由于系统自动运行的进程和脚本就没有控制终端,所以他们不能打开/dev/tty。

3.3 /dev/null

空设备,是一个特殊的设备文件,它会丢弃一切写入其中的数据,写入它的内容都会永远丢失,而且没有任何可以读取的内容。
因此,null这个设备通常也被称为位桶(bit bucket)或黑洞。

4. 系统调用和设备驱动程序

4.1 系统调用

操作系统本身提供的接口,由linux直接提供
包括: open,close,read,write和ioctl(把控制信息传递给设备驱动程序)

定义: 进程直接调用内核暴露出来的的接口的方式称为系统调用

4.2. 库函数

4.2.1. 系统调用的缺点:

		1. 效率低 每次调用都是从用户态进入内核态,然后再返回用户态
		2. 硬件限制对底层系统调用一次读取数据的大小。
		如磁带机一次读取大小是10k,若传递的不是10k的整数倍,还会以10k存储,会留下空隙。
	库函数应运而生,它是一些函数的集合。

4.2.2 库函数定义

调用将内核暴露出来的接口封装好的函数的方法为库函数的调用

4.2.3. 系统函数和库函数的关系

  1. 系统调用通常是用于底层文件的访问
    例如在驱动程序中对设备文件的直接访问,如open read write seek等

  2. 库函数是对系统调用的一层封装
    因此在用库函数对文件操作的时候,必然会引起系统调用。也就是说,库函数调用实际上是通过系统调用实现的
    例如:C库函数fwrite()就是通过write实现的。

  3. 运行位置
    库函数:在用户态调用,在用户态执行
    系统调用函数:在用户态调用,在内核态执行

  4. 执行效率
    当处理的数据量比较小时,函数库的函数执行效率比较好
    因为函数库的函数的作法是将要处理的数据先存入缓冲区内,等到缓冲区装满了,再将数据一次写入或者读出。这种方式处理小量数据时效率比较高。
    但是在进行系统调用时,因为用户进程从用户模式进入系统内核模式,中间涉及了许多额外的任务的切换工作,这些操作称为上下文切换,此类的额外工作会影响系统的执行效率。

参考之前的博客:
https://blog.csdn.net/lqy971966/article/details/103657953

5. 三个文件描述符:

	0 标准输入
	1 标准输出
	2 标准错误

6. write

6.1 原型

#include
size_t write(int fildes, const void *buf, size_t nbytes);

6.2. write 功能:

把缓冲区buf的前nbytes个字节写入与文件描述符fildes关联的文件中。

6.3. 返回值:

返回实际写入的字节数。
返回0表示未写入任何数据
返回 -1 表示出错。错误代码保存在全局变量errno中。

6.4. 代码:

		#include
		#include
		int main()
		{
			char str[] = "Hani test\n";
			int len = sizeof(str);
			if((write(1, str, len)) != len)
					write(2, "error\n", 6);
			
			return 0;
		}
		结果: 
		root@admindlp-virtual-machine:/home# ./a.out 
		Hani test

7. read

7.1 原型

	#include
	size_t read(int fildes, void *buf, size_t nbytes);

7.2 read 功能

从与文件描述符fildes相关的文件里读入nbytes个字节的数据放到缓冲区buf中。

7.3 返回值

返回实际读取的字节数。
返回-1,错误。
返回0,表示未读入任何数据。

7.4. 代码:

	#include
	#include
	int main()
	{
		char buf[128];
		int nread;
		
		nread = read(0, buf, 128);
		if(nread == -1)
			write(2, "read error\n", sizeof("read error\n"));
		
		if((write(1, buf, nread)) != nread)
			write(2, "write error\n", sizeof("write error\n"));
		
		return 0;
	}
	结果: 
	root@admindlp-virtual-machine:/home# echo hello hani | ./a.out 
	hello hani

你可能感兴趣的:(读书与人生感悟)