CSAPP笔记
1.shell程序设计
2.内存管理
3.链接库
4.文件操作
5.多进程
6.多线程
7.网络编程
8.makefile
9.调试技巧与调试工具
前言
学习文件的创建、打开、读写、关闭操作。
学习目录的创建、扫面、删除操作。
一、基础知识
- 对文件和目录进行处理有两种方式:
a. 系统调用(效率低、受硬件特点限制)
b. 标准I/O库(对应头文件为stdio.h)
推荐使用标准I/O库,降低系统调用的开销。 - Linux中文件为操作系统服务和设备提供了一个简单而一致的接口,普通文件、目录和设备都被视作文件。
- 根目录下的内容:
二级子目录 | 存放的内容 |
---|---|
/bin | 系统程序的二进制可执行文件 |
/etc | 系统配置文件 |
/lib | 系统函数库文件 |
/dev | 物理设备接口文件 |
/home | 直接使用cd命令进入自己的家目录 |
/proc | 硬件状态信息文件 |
- Linux中比较重要的设备文件:
/dev/console
、/dev/tty
、/dev/null
。 - 因为设备也是一种文件,所以设备按是否需要一次读写一整块,可以被分为字符设备和块设备。一般情况下块设备是那些支持某些类型文件系统的设备,如硬盘。
- 用于对文件和设备进行访问和控制的函数称为系统调用,由Linux直接提供,它们也是通向操作系统本身的接口。
- 操作系统的核心部分——内核,是一组设备驱动程序。它们是一组对系统硬件进行控制的底层接口。
- 为了向用户提供一个统一的接口,设备驱动程序封装了所有与硬件相关的特性。硬件的特有功能通过ioctl(用于I/O控制)系统调用来提供,ioctl调用提供了一些与特定硬件设备有关的必要控制,用法因设备而异。
用于访问设备驱动程序的系统调用:open、 read、 write、close、 ioctl
- 一个程序开始运行产生进程时,一般会有3个已经打开的文件描述符:0标准输入、1标准输出、2标准错误。
10.常见的文件有关的系统调用见红书3.4底层文件访问。
常见的标准I/O库见红书3.5标准I/O库。
1.文件复制
采用系统调用,编写一个底层程序copy_system.c,用来逐个字符地将一个文件复制到另一个文件。假设输入文件已经存在,输出文件不存在。
#include <unistd.h>//首先包含
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main(){
char c;//定义1字符的缓冲区
int in, out;//定义两个文件的描述符
in = open("file.in", O_RDONLY);
out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
while(read(in, &c, 1) == 1){
write(out, &c, 1);
}
exit(0);
}
该程序复制字符很多的文件时,进行大量的系统调用,速度非常慢。
对程序进行改进,每次复制大一些的数据块。
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main(){
char block[1024];//定义1字符的缓冲区
int in, out;//定义两个文件的描述符
int nread;
in = open("file.in", O_RDONLY);
out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
while((nread = read(in, block, sizeof(block))) > 0){
write(out, block, nread);
}
exit(0);
}
采用标准I/O函数实现文件复制。
从键盘输入被复制文件的名字
#include <stdio.h>
#include <stdlib.h>
int main(){
char filename[10];
int c;
FILE *in, *out;
printf("please enter the file name");
scanf("%s", filename);
in = fopen(filename, "r");
if((out = fopen("file.out", "w")) == NULL){
printf("unable to open the file");
exit(0);//终止程序
}
//out = fopen("file.out", "w");
while((c = fgetc(in)) != EOF){//c = EOF时表示文件流到达文件尾
fputc(c, out);//把字符c写到一个输出文件流中
}
fclose(in);
fclose(out);
exit(0);
}
顺序读写数据文件基本框架:
- 先用fopen打开文件,并与定义好的文件流建立关联。
- 再用fgetc和fputc操作文件流,一般会使用一个中间变量临时存放读出的字符。使用whlie循环遍历整个文件。
- 关闭刚才打开的文件。
顺序读写读取了太多不需要的信息,如果想要读取指定的数据,就需要用到随机读写。
实现随机读写的关键是要按要求移动位置指针,也就是文件的定位。
移动文件内部的位置指针的函数主要有两个,即 rewind() 和 fseek()。
要说明的是 fseek 函数一般用于二进制文件。在文本文件中由于要进行转换,故往往计算的位置会出现错误。
2.扫描目录
- Linux扫描目录有两种方式做到:
a. shell程序设计,用表达式的通配符扩展。
b. 使用dirent.h头文件中定义的一套目录操作库函数。