unix环境高级编程(上) 您所在的位置:网站首页 unix的文件系统 unix环境高级编程(上)

unix环境高级编程(上)

2024-07-08 03:53| 来源: 网络整理| 查看: 265

目录前言unix基础知识unix标准化和实现unix提供的文件IO文件和目录标准IO系统数据文件前言

笔者将《unix环境高级编程》主要内容总结为三篇:文件篇,进程篇,高级io和进程间通信三大板块。本文是unix环境高级编程系列文章第一篇:文件篇。该篇主要包括:

unix基础知识

介绍了unix的体系结构,以及unix中的文件和目录,输入输出,程序和进程,信号等基本概念

unix标准与实现

标准包括C语言的标准和操作系统标准,实现包括BSD,FreeBSD,Linux,Solari,Mac os等

unix内核提供的文件io函数

包括文件描述符,对文件的打开,关闭,定位,读,写,改变文件属性操作。内核IO调用基于文件描述符。还介绍了文件的底层数据结构,了解数据结构之后就能理解文件是如何支持共享的

文件和目录

主要介绍文件的属性和属性对应的数据结构,以及各个字段控制的问访问权限,文件类型等。unix中一切皆文件,这些文件包括:普通文件,目录文件,块特殊文件,字符特殊文件,FIFO,套接字和符号链接。最后结束UFS文件系统。

标准IO函数

标准io解决了内核io的很多细节问题,包括缓冲区分配。所有操作基于流和File对象

系统数据文件

最后介绍系统提供的一些数据文件,包括口令文件,阴影文件,朱文杰,登录账号文件,服务数据文件,协议数据文件,网络数据文件等

一. unix基础知识1. unix体系结构操作系统是一种特殊的软件,它控制计算机硬件资源,提供程序运行环境此软件称为内核,它相对较小,位于环境的中心内核的接口被称为系统调用公共函数库构建在系统调用接口上系统调用一般比普通函数调用需要花费更多时间应用软件可以调用公共函数库或者使用系统调用 2. 文件和目录文件系统是目录和文件组成的一种层次结构目录的起点称为根,名称为/符号目录是包含很多目录项的文件逻辑上可认为每个目录项都包含文件名和文件属性。物理上是不包含的,因为一个文件可被多次硬链接文件属性包括:类型(普通文件,目录),大小,所有者,权限,修改时间等。state和fstate函数返回文件属性。3. 输入和输出3.1 文件描述符

通常是一个小的非负整数,内核用它标识一个特定进程正在访问的文件

3.2 标准输入,标准输出,标准出错

每当运行一个新程序时,shell都为其打开三个文件描述符:

说明

文件描述符

头文件

标准输入

0

STDIN_FILENO

标准输出

1

STDOUT_FILENO

标准出错

2

STDERR_FILENO

3.3 不用缓冲的io函数open,read,write,lseek,close提供了不用缓冲的io这些函数都使用文件描述符头文件为3.4 标准io标准io提供一种带缓冲io的接口使用标准io无需担心如何选取最佳缓冲区大小,且简化了堆输入行的处理标准io头文件为4. 程序和进程4.1 程序存放在磁盘,处于某个目录中的可执行文件exec函数执行时,内核将程序读入存储器并执行4.2 进程程序的执行实例被称为进程每个进程都有一个唯一的数字标识,称为进程ID4.3 进程控制

进程控制的主要函数:fork,exec和waitpid

4.4 线程进程内所有线程共享同一个地址空间,文件描述符,栈,进程相关属性线程访问共享数据时需要采取同步措施避免不一致性线程也用ID标识,但是只在它所属进程内起作用5. 信号信号是通知进程已发生某种情况的一种技术进程如何处理信号有三种选择: 忽略该信号按系统默认方式处理捕捉该信号:提供一个函数,信号发生时调用该函数。调用signal函数,第一个参数为信号名称,第二个参数为处理函数6. 时间值

unix系统一直使用两种不同的时间值

日历时间:UTC时间,用time_t表示。记录自1970年1月1日以来锁经过的秒数进程时间:cpu时间,用clock_t表示。已时钟滴答计算二. unix标准化和实现1. unix标准化ISO c:c语言国际化标准POSIX:可移植的操作系统接口(protable operating system interface)2. unix实现SVR4:AT&T的UNIX系统实验室产品,初版了系统V接口定义BSD:加州伯克利分校研究和开发的,含有AT&T许可证的代码FreeBSD:BSD去除AT&T许可证代码后,完全免费的版本Linux:1991年Linux开发的一款被目前广泛使用的unix操作系统Mac OS:核心系统是Darwin,基于Mach内核和FreeBSD的组合Solaris:sun公司开发的unix系统版本三. unix提供的文件IO1. 文件描述符内核中,所有打开的文件都通过文件描述符引用打开,新建时,内核向进程返回一个文件描述符读写文件时,将文件描述符传给read和write2. open作用:创建或打开一个文件pathname参数:文件名字flag参数:由以下值进行“或”组成 O_RDONLY:只读O_WRONLY:只写O_RDWR:读写O_APPEND:追加到末尾O_CREATE:文件不存在就创建O_EXCL:同时指定O_CREATE时,如果文件存在,就会出错。使测试和创建成为原子操作O_TRUNC:将文件长度截短为0O_NOCTTY:控制终端相关O_NONBLOCK:非阻塞模式mode参数:文件访问权限,仅新建文件时使用该参数3. create作用:创建文件等价于open(pathname, O_WRONLY|O_CREATE|O_TRUNC, mode) 4. close作用:关闭文件关闭会释放加在该文件上的所有记录锁进程终止时,内核自动关闭它打开的文件,故可以不用显示调用close5. lseek作用:设置打开文件的偏移量默认偏移量为0,如果设置O_APPEND属性,默认偏移量为文件末尾whence的取值: SEEK_SET:设置文件偏移为pos值SEEK_CUR:设置文件偏移为当前位置+posSEEK_END:设置文件偏移为文件长度+pos6. read作用:从打开的文件中读数据读取成功,返回读到的字节数。读到末尾,返回0。导致读到的字节数小于要求读字节数的情况: 普通文件:读到达到要求字节数时,已经读到文件结尾了终端设备文件:一次最多读一行网络数据:缓存区大小小于要读字节管道文件:管道包含的字节小于要读字节7. write作用:向打开文件中写数据返回值通常与nbyte相同,否则出错写成功后,文件偏移量增加写入字节数量9. 文件共享9.1 打开文件的内核数据结构

unix支持在不同进程间共享打开的文件,unix内核使用什么数据结构来支持这种共享呢?

进程表记录来所有的进程每个进程都有一个记录项,用来记录打开文件的文件描述表文件描述符的每一项包括: 文件描述符标识指向文件表项的指针文件表项由内核维护,每一项包括: 文件状态标识(读,写,同步,阻塞等)当前文件偏移量指向该文件v节点表项的指针每个打开文件都有v节点(v-node)结构,这些信息是打开文件时从磁盘读入内存的。包括: 文件类型对此文件进行各种操作的指针i节点信息(索引信息):包括长度,所有者,所在设备,磁盘位置指针等9.2 两个独立进程各自打开同一文件给定的文件,只有一个v节点表项每个进程都有自己的文件表项,以使自己有独立的文件偏移量9.3 两个独立进程共享同一个文件表项使用dup和fork函数时,父子进程对于每一个文件描述符,都共享同一个文件表项,达到文件共享的目的9.4 创建共享文件的函数dup:返回的文件描述符为可用的最小值dup2:返回fieldes2指定的描述符。如果fieldes2已经打开,就关闭。如果fieldes=fieldes2,不关闭,直接返回。fcntl:也可以创建共享文件10. 原子操作原子操作:指多步组成的操作,任何一个需要调用多个函数的操作都不可能是原子操作,因为中间可能会挂起该进程unix提供了一些函数,使多个操作成为一个“原子操作”O_APPEND标识:lseek和write的原子操作pread:lseek和read的原子操作pwrite:lseek和write的原子操作调用open时,通过制定O_CREAT和O_EXCL参数,将创建文件作为原子操作11. sync, fsync, fdatasync函数

这几个函数出现的背景:unix提供的延时写功能,通过提供缓冲区以减少磁盘读写次数,但是降低了文件内容更新速度,这几个函数用于保证缓冲区内容与文件内容的同步,保证一致性。

sync:将修改的快缓冲区排入写队列,立马返回,不等待真正写磁盘fsync:针对指定的文件描述符起作用,且等待磁盘写完才返回。同步内容包括数据和文件属性。适用于数据库系统。fdatasync:包括fsync的功能,但是只同步数据,不同步文件属性。12. fcntl函数作用:改变已打开文件的性质参数cmd的取值和作用: F_DUPFD:复制一个现有的文件描述符F_GETFD: 设置文件描述符标记F_SETFD: 获得文件描述符标记F_GETFL: 设置文件状态标记:读,写,追加,阻塞等。F_SETFL: 获得文件状态标记F_GETOWN: 设置异步io所有权F_SEGOWN: 获得异步io所有权F_GETLK:获得记录锁F_SETLK:设置记录锁F_SETLKW:设置记录锁四. 文件和目录1. 文件属性1.1 表示文件属性的数据结构:struct stat代码语言:javascript复制

struct stat {

代码语言:txt复制mode_t st_mode; //文件模式,包含文件类型,用户id,组id,访问权限(9种)等信息代码语言:txt复制ino_t st_ino; //inode节点号代码语言:txt复制dev_t st_dev; //设备号码代码语言:txt复制dev_t st_rdev; //特殊设备号码代码语言:txt复制nlink_t st_nlink; //文件的连接数代码语言:txt复制uid_t st_uid; //文件所有者代码语言:txt复制gid_t st_gid; //文件所有者对应的组代码语言:txt复制off_t st_size; //普通文件,对应的文件字节数代码语言:txt复制time_t st_atime; //文件数据最后被访问的时间代码语言:txt复制time_t st_mtime; //文件数据最后被修改的时间代码语言:txt复制time_t st_ctime; //文件状态(i节点状态)的最后修改时间代码语言:txt复制blksize_t st_blksize; //文件内容对应的块大小代码语言:txt复制blkcnt_t st_blocks; //伟建内容对应的块数量

};

代码语言:txt复制1.2 如何获取文件属性state:根据文件名获取属性fstate:根据描述符获取属性lstate:返回符号链接的属性1.3 修改属性的部分方法访问时间和修改时间: utime函数,参数为struct utimbuf,每一项都是utc时间文件用户id和组id:chown,fchown,lchown 2. 文件类型:2.1 st_mode字段控制的文件类型S_ISREG:普通文件。文本或二进制;可执行文件有固定的可被内核识别的格式。S_ISDIR:目录文件。包含其他文件的名字以及指向与这些文件有关信息的指针。S_ISBLK:块特殊文件。提供堆设备(如磁盘)带缓冲的访问,访问长度固定。S_ISCHR:字符特殊文件。提供堆设备(如磁盘)不带缓冲的访问,访问长度不固定。S_ISFIFO:FIFO,命名管道。用于进程间通信S_ISSOCK:套接字。用于网络间进程通信S_ISLINK:符号链接。指向另一个文件2.2 stat结构体本身控制的文件类型S_TYPEISMQ:消息队列S_TYPEISSEM:信号量S_TYPEISSHM:共享存储对象3. 文件访问权限权限位保存在st_mode属性中9个访问权限位对应的值为: 更改文件访问权限的函数:chmod和fchmod 4. UFS文件系统4.1 磁盘,分区和文件系统图一个磁盘分为多个分区,每个分区可以包含一个文件系统i节点是固定长度的记录项4.2 详细的柱面组的i节点和数据块每个柱面包括:i节点数组,数据库,目录块每个i节点包含文件的大部分信息:文件类型,访问权限,长度,占用的实际数据库。(stat结构大多数信息取自i节点)每个目录块包括:目录名称,i节点号同一个i节点,可以被不同的目录指向,i节点的链接计数统计指向的数量文件改名时,实际内容并未移动,只是构造一个新目录项,指向现有的节点,并解除旧记录项的链接5. 硬链接

硬链接直接指向文件的i节点

5.1 创建一个指向现有文件的链接:link方法如果newpath已经存在,返回出错只能创建newpath中最后一个分量,路径中其他部分必须已经存在很多文件系统不允许堆目录创建硬链接超级用户能直接创建目录硬链接5.2 删除一个现有的链接项:unlink方法将path所引用的文件的链接数减1只有当连接技术为0,该文件的内容才被删除对于文件,可以使用remove功能,和unlink一样对于目录,可以使用rmdir功能,和unlink一样6. 符号链接

符号链接是指向一个文件的间接指针。

6.1 符号链接是为了避开硬链接的一些限制硬链接要求链接和文件位于同一文件系统中只有超级用户才能创建指向目录的硬链接6.2 使用符号链接需要注意的事情当调用某个函数时,需要注意函数处理的是链接的文件,还是链接本身6.3 符号链接相关的函数创建符号链接: symlink打开符号链接:readlink7. 目录创建目录:mkdir删除目录:rmdir。入炉链接计数为0,且没有进程打开次目录,释放目录空间。读取目录: 更改当前工作目录:chdir,fchdir五. 标准IO标准io库不仅在unix上,很多操作系统上都实现了。标准io处理很多细节,例如:缓冲区分配,优化长度执行io等。便于用户使用。使用的头文件为。标准io的底层调用了前面介绍的unix内核io。标准io的缺点是效率低。这与它需要复制的数据量有关1. 流和File对象unix内核io提供的io函数都是针对文件描述符的但是标准io的操作是针对流进行的标准io文件流可用于单字节或宽字节字符集,由流定向决定(fwide函数)。标准io打开一个文件(fopen函数)时,返回一个FILE的指针,它包含了实际io的文件描述符,指向用于该流缓冲区的指针,缓冲区长度,缓冲区当前字符数,出错标志,文件结束标志等信息每个进程预定义三个流:标准输入,标准输出,标准出错2. 缓冲2.1 缓冲类型

标准io提供三种类型的缓冲

全缓冲:填满标准io缓冲区后才进行实际的io操作(malloc申请缓冲区,flush执行写操作)。行缓冲:输入输出中遇到换行符时进行实际的io操作。涉及终端设备时,通常用行缓冲。不带缓冲:不对字符进行缓冲存储。标准出错流通常不带缓冲。2.2 设置缓冲类型setbufsetvbuf:第三个参数: _IOFBF:全缓冲_IOLBF: 行缓冲_IONBF:无缓冲3. 打开流fopen:打开一个指定的文件freopen:将一个文件读到一个指定的流。如果流已经打开,就先关闭,已经定向,就先清除定向。fdopen:通过文件描述符打开文件。因为管道和网络通信等特殊文件不能用标准io函数fopen打开,所以用到该函数。type:指定文件的打开方式 4. 读和写流

读写流有三种不同的方式

每次读写一个字符: 读:getc,fgetc,getchar写:putc,fputc,putchar

不带f前缀的从标准输入流读取数据,带f前缀的从指定流读取数据。不带f前缀的函数不推荐使用,因为它不指定缓冲区大小,会导致溢出。

每次读写一行: 读:gets,fgets写:puts,fputs每次读写一定数量的对象(直接io,二进制io): 读:fread,需要指定要读取的元素个数和每个元素的大小写:fwrite缺点:不同系统间,交换二进制数据会编译期和计算机体系结构不同而有差异,所以必须用更高级的协议。5. 定位流

定位标准io流有三种不同的方式

ftell(获取),fseek(设置):long类型的文件位置ftello和fseeko:off_t类型的文件位置fgetpos和fsetpos:fpos_t的抽象数据类型表示文件位置6. 格式化io6.1 格式化输出printf:格式化数据写到标准输出fprintf:格式化数据到指定流sprintf:格式化的数据送入数组buf中,尾部自动加入null。可能会导致缓冲区溢出,需调用者自己保证转换说明以%开始6.2 格式化输入六. 系统数据文件1. 口令文件存放目录:/etc/passwd数据结构:中的passwd结构体查看指定用户口令的函数接口: 查看所有用户口令的函数接口: 2. 阴影文件(加密口令)存放目录:/etc/shadow查看的接口: 3. 组文件存放目录:/etc/group数据结构:中的group查看指定组: 查看所有组: 4. 其他数据文件服务器提供服务的数据文件:/etc/services记录协议信息的数据文件:/etc/protocols记录网络信息的数据文件:/etc/networks 5. 登陆账号文件当前登陆进系统的用户:/var/run/utmp 跟踪登陆和注销信息:/var/log/wtmp6. 获取系统信息获取主机与操作系统相关信息 只获取主机名 7. 时间格式日历时间(UTC时间) 更高精度的时间 各种时间的转化关系


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有