第七、八章学习笔记(1)

第七、八章学习笔记

一、课本知识

1.文件操作级别

(1)硬件级别
硬件级别的文件操作包括:

  • fdisk:将硬盘、U盘或SDC盘分区。
  • mkfs:格式化磁盘分区,为系统做好准备
  • fsck:检查和维修系统
  • 碎片整理:压缩文件系统中的文件

(2)操作系统内核中的文件系统函数: 每个操作系统内核均可为基本文件操作提供支持

(3)系统调用: 用户模式程序使用系统调用来访问内核函数
(4)I/O库函数
(5)用户命令:用户可以使用Unix/Linux命令来执行文件操作而不是编写程序

     用户命令的示例如下:
     mkdir,rmdir,cd,pwd,ls,link,unlink,rm,cat,cp,mv,chmod,etc.

      每个用户命令实际上是一个可执行程序(cd除外),通常会调用库I/O函数,而库I/O函数再发出系统调用来调用相应的内核函数。

2.文件I/O操作:

(1) 用户模式下的程序执行操作
FILE _Ep = fopen ("file","r"); or 室ILE_Ep = fopen ( "tile","w"')1可以打开一个读/写文件流。
( 2 ) fopen() 在用户( heap)空间中创建一个FILE结构体,包含一个文件描述符fd、一个fbuf [BLKSIZE]和一些控制变量。
( 3 ) fread(ubuf, size, nitem, fp): 将nitem个size字节读取到ubuf上,通过:·将数据从FILE结构体的fbuf上复制到ubuf上,若数据足够,则返回。·如果 fbuf没有更多数据,则执行(4a)。
(4)

  • fread(fd,fbuf, BLKSIZE)系统调用,将文件数据块从内核读取到 fbuf上,然后将数据复制到ubuf上,直到数据足够或者文件无更多数据可复制。
  • fwrite(ubuf, size, nitem, fp):将数据从ubuf复制到fbuf。·若(fbuf有空间):将数据复制到fbuf 上,并返回。
    ·若(fbuf已满):发出 write(fd,fbuf,BLKSIZE)系统调用,将数据块写入内核,然后再次写入fbuf。
    这样,fread()/fwrite()会向内核发出read(/write)系统调用,但仅在必要时发出,而且它们会以块集大小来传输数据,提高效率。同样,其他库I/O函数,如 fgetc/fputc、fgetsllputs、fscanf/fprintf等也可以在用户空间内的FILE结构体中对fbuf进行操作。
    (5)内核中的文件系统函数:
    假设非特殊文件的 read(fd, fbuf[ ], BLKSIZE)系统调用。
    (6)在read()系统调用中,fd是一个打开的文件描述符,它是运行进程的f数组中的一个索引,指向一个表示打开文件的OpenTable。
    ( 7 ) OpenTable包含文件的打开模式、一个指向内存中文件INODE的指针和读/写文件的当前字节偏移量。从 OpenTable的偏移量, 计算逻辑块编号1bk。通过INODE.i_block[ ]数组将逻辑块编号转换为物理块编号blk。
    ( 8 ) Minode包含文件的内存 INODE。EMODE.i_block[ ]数组包含指向物理磁盘块的指针。文件系统可使用物理块编号从磁盘块直接读取数据或将数据直接写入磁盘块,但将会导致过多的物理磁盘I/O。
    (9)为提高磁盘IO效率,操作系统内核通常会使用一组IO缓冲区作为高速缓存,以减少物理I/O的数量。
    • 对于read(fd, buf, BLKSIZE)系统调用,要确定所需的(dev,blk)编号,然后查询I/O缓冲区高速缓存。
    • 对于write(fd, fbuf, BLKSIZE)系统调用,-要确定需要的(dev,blk)编号,然后查询I/O缓冲区高速缓存。

(10)设备I/O: Io缓冲区上的物理IO最终会仔细检查设备驱动程序,设备驱动程序由上半部分的start_io()和下半部分的磁盘中断处理程序组成。


3. 低级别文件操作:

  • 分区
  • 格式化分区
  • 挂载分区

4.简单的系统调用

access:检查对某个文件的权限  
int access(char *pathname, int mode);chdir:更改目录  
int chdir(const char *path);chmod:更改某个文件的权限  
int chmod(char *path, mode_t mode) ;chown:更改文件所有人  
int chown (char *name, int uid, int gid);chroot:将(逻辑)根目录更改为路径名int chroot (char *pathname) ;  
getcwd:获取CWD的绝对路径名char *getcwd(char *buf, int size);  
mkdir:创建目录  
int mkdir (char *pathname, mode_t mode);  
rmdir:移除目录(必须为空)  
int rmdir(char *pathname );  
link:将新文件名硬链接到旧文件名  
int link (char *oldpath, char *newpath) ;  
unlink:减少文件的链接数;如果链接数达到0,则删除文件int unlink (char *pathname);  
symlink:为文件创建一个符号链接  
int symlink(char *oldpath,char *newpath);rename:更改文件名称  
int rename(char *oldpath, char *newpath);utime:更改文件的访问和修改时间  
int utime(char *pathname, struct utimebuf *time)以下系统调用需要超级用户权限。  
mount:将文件系统添加到挂载点目录上  
intmount(char *specialfile, char *mountDir);  
umount:分离挂载的文件系统  
int umount (char *dir) ;  
mknod:创建特殊文件

5.常用的系统调用

stat:获取文件状态信息  
open:打开一个文件进行读、写、追加  
int open(char *file, int flags, int mode)close:关闭打开的文件描述符  
int close(int fd)  
read:读取打开的文件描述符  
int read(int fd,char buf[ 1, int count)write:写入打开的文件描述符  
int write(int fa,char buf[ 1, int count)  
lseek:重新定位文件描述符的读/写偏移量int lseek ( int fa, int offset, int whence)  
dup:将文件描述符复制到可用的最小描述符编号中int dup(int oldfd) ;  
dup2:将oldfd复制到newfd 中,如果newfd已打开,先将其关闭int dup2(int oldfa,int newfd)  
link:将新文件硬链接到旧文件  
int link(char *o1dPath, char *newPath)  
unlink:取消某个文件的链接;如果文件链接数为0,则删除文件int unlink(char *pathname) ;  
symlink:创建一个符号链接  
int symlink(char *target,char *newpath)  
readlink:读取符号链接文件的内容  
int readlink(char *path,char *buf, int bufsize)  
umask:设置文件创建掩码;文件权限为( mask & ~umask)

6.read系统调用

系统调用read是从文件中读出数据。要读取的文件用文件描述符标识,数据读入一个事先定义好的缓冲区。他返回实际读入的字节数。
Linux中read的函数原型:
size_t read(int fildes, void buf, size_t nbytes);

参数说明:

  • fildes:文件描述符,标识要读取的文件。如果为0,则从标准输入读数据。类似于scanf()的功能。
  • *buf:缓冲区,用来存储读入的数据。
  • nbytes:要读取的字符数。

返回值:size_t返回成功读取的字符数,它可能会小于请求的字节数。

7.write系统调用

write,就是把缓冲区的数据写入文件中。注意,这里的文件时广泛意义的文件,比如写入磁盘、写入打印机等等。
Linux 中write()的函数原型:
size_t write(int fildes, const void *buf, size_t nbytes);

参数说明:

  • fildes:文件描述符,标识了要写入的目标文件。例如:fildes的值为1,就像标准输出写数据,也就是在显示屏上显示数据;如果为 2 ,则想标注错误写数据。
  • *buf:待写入的文件,是一个字符串指针。
  • nbytes:要写入的字符数。

函数返回值:size_t 返回成功写入文件的字符数。需要指出的是,write可能会报告说他写入的字节比你所要求的少。这并不一定是个错误。在程序中,你需要检查
error已发现错误,然后再次调用write写入剩余的数据。

二、知识点挑战

1.





2.I/O库模式

三、遇到的问题

1.代码调试问题

虽然学习C语言已经一年,也已经写过一些代码了,但是还是在一些语法上出现了错误
调试中出现该问题:

因为对Linux系统还是有陌生、畏难心理,而该错误也是不曾碰到过的,于是向gpt闻讯问题在哪

虽然在codeblocks上已经使用过一次,但是并未发现大小写的错误。于是及时纠正了这一问题

2.文件权限问题

在使用gcc调试的过程中,出现了该报错

向gpt询问产生该报错的原因
于是在这些原因中找到了可能导致gcc报错的那种可能性——文件权限问题,在更改了test.txt文件权限之后,便可以读出文件内容

posted @ 2023-09-28 08:27  20211113  阅读(20)  评论(0)    收藏  举报