lienhua342014-09-16 1 文件的时间 每个文件都有三个时间字段,如表 1 所示. 表 1: 文件的三个时间字段 说明 字段 st_atime 文件数据的最后访问时间 st_mtime 文件数据的最后修改时间 st_ctime i 节点状态的最后更改时间 最后修改时间是文件内容最后一次被修改的时间.更改状态时间是该文件的 i 节点最后一次被修改的时间. 2 utime 函数 utime 函数提供了对文件最后访问时间和最后修改时间的更改功能. #include <utime.h>…
lienhua342014-09-29 1 标准 I/O 流 之前学习的都是不带缓冲的 I/O 操作函数,直接针对文件描述符的,每调用一次函数可能都会触发一次系统调用,单次调用可能比较快捷.但是,对于需要频繁进行 I/O 操作的程序,频繁触发系统调用产生的消耗太大. 标准 I/O 库提供了带缓冲的 I/O 操作函数,这些函数围绕着一种叫做流(stream)的东西进行.当使用标准 I/O 库打开或创建一个文件时,系统提供了一个流与这个文件相关联.通过流的读入和输出完成所需要的 I/O操作. 标准…
lienhua342014-09-18 1 引言 在 UNIX 系统中,目录是一种特殊的文件类型.我们可以使用 open 函数来打开目录,获取文件描述符,然后调用 stat 函数来获取目录的属性信息,但是我们却不能够使用 read 函数来读取目录内容.例如,下面例子所示, #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <fcn…
lienhua342014-09-15 1 文件系统数据结构 UNIX 文件系统通过 i 节点来存储文件的信息.如图 1 所示为一个磁盘柱面上的 i 节点和数据块示意图.其中 i 节点是一个固定长度的记录项,它包含了有关文件的大部分信息.数据块用于存储文件的实际内容.每个文件的 i 节点会记录该文件的内容所占用的数据块信息. 图 1: i 节点和数据块 图 1 中还有一些信息需要进行说明: 1. 每个目录项只存储了文件的文件名和 i 节点编号(每个文件系统各自对它们的 i 节点进行编号).文件的…
lienhua342014-09-10 1 文件访问权限 在文件访问权限和进程访问控制中,我们已经讲述过文件访问权限位,为了方便,我们重新列在下面, 表 1: 文件的 9 个访问权限位  st_mode 屏蔽  意义  S_IRUSR  用户 -读  S_IWUSR  用户 -写  S_IXUSR  用户 -执行  S_IRGRP   组 -读  S_IWGRP  组 -写  S_IXGRP  组 -执行  S_IROTH  其他 -读  S_IWOTH  其他 -写  S_IXOTH  其他…
lienhua342014-09-03 通过前面一篇随笔(文件访问权限与进程访问控制),我们知道内核校验文件的访问权限使用的是进程的有效用户 ID 和有效组 ID.但有时我们需要知道当前登录用户对某个文件访问权限.虽然说进程的有效用户 ID 和有效组 ID 通常分别等于当前登录用户 ID 和用户所在组 ID.例如,一个进程可能因设置用户 ID 以另一个用户权限运行,它仍可能想验证当前实际登录的用户是否能否访问一个给定的文件. access 函数提供了按照实际用户 ID 和实际组 ID 进行访问权…
lienhua342014-09-02 1 文件的设置用户 ID位 和设置组 ID位 与进程相关联的 ID 如下表所示, 表 1: 与进程相关联的用户 ID 和组 ID 实际用户 ID 我们实际上是谁 实际组 ID 有效用户 ID 用于文件访问权限检查 有效组 ID 附加组 ID 保存的设置用户 ID 由 exec 函数保存 保存的设置组 ID 保存的设置用户 ID 和保存的设置组 ID 在执行一个程序时包含了有效用户 ID 和有效组 ID 的副本,这个后面我们学习到进程时在详细学习. 此处,我…
lienhua342014-09-01 1 文件类型 我们平时最常接触的文件类型有普通文件(regular file)和目录(di-rectory file),但是 UNIX 系统提供了多种文件类型: (1) 普通文件(regular file) 这种文件包含了某种形式的数据,这些数据无论是文件还是二进制对于 UNIX 内核而言都是一样的.对普通文件内容的解释有处理该文件的应用程序进行. (2) 目录文件(directory file) 目录文件包含了其他文件的名字以及指向与这些文件有关信息的指…
lienhua342014-08-27 内核使用三种数据结构表示打开的文件,分别是文件描述符表.文件表和 V 节点表. (1) 每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,每个描述符占用一项.与每个文件描述符相关联的是: (a) 文件描述符标志. (b) 指向一个文件表项的指针. (2) 内核为所有打开文件维持一张文件表.每个文件表项包含: (a) 文件状态标志(读.写.添写.同步和非阻塞等). (b) 当前文件偏移量. (c) 指向该文件 V 节点表项的指针. (3)…
lienhua342014-08-25 1 文件描述符 对于内核而言,所有打开的文件都通过文件描述符引用.文件描述符是一个非负整数.当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符.当读或写一个文件时,使用 open 或 creat 返回的文件描述符标识该文件,将其作为参数传送给 read 或 write. 按照惯例,UNIX 系统 shell 使用文件描述符 0 与进程的标准输入相关联,文件描述符 1 与进程的标准输出相关联,文件描述符 2 与进程的标准出错输出相关联. 2…
lienhua342014-10-01 ISO C 标准 I/O 库提供了个两个函数 tmpnam 和 tmpfile 以帮助创建临时文件, #include <stdio.h> char *tmpnam(char *ptr); 返回值:指向唯一路径名的指针 tmpnam 函数产生一个与现有文件名不同的一个有效路径名字符串.每次调用它时,它都产生一个不同的路径名,最多调用次数是TMP_MAX.TMP_MAX 定义在 <stdio.h> 中. 若 ptr 是 NULL,则产生的路径名…
lienhua342014-10-12 当一个进程正常或者异常终止时,内核就向其父进程发送 SIGCHLD信号.父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用的函数(信号处理程序).对于这种信号的系统默认动作是忽略它. 在文档“进程控制三部曲”中,我们讲的第三部曲是使用 wait 函数来获取终止子进程的终止状态.那么,有几个问题我们这里需要详细的学习一下. 1. 父进程一定能够获取到子进程的终止状态吗?如果子进程在父进程调用 wait 函数前就终止了,怎么办? 2. 如果父进程没有获…
lienhua342014-10-07 在“进程控制三部曲”中,我们学习到了 fork 是三部曲的第一部,用于创建一个新进程.但是关于 fork 的更深入的一些的东西我们还没有涉及到,例如,fork 创建的新进程与调用进程之间的关系.父子进程的数据共享问题等.fork 是否可以无限制的调用?如果不行的话,最大限制是多少?另外,我们还将学习一个 fork 的变体 vfork. 1 fork 创建的新进程与调用进程之间的关系 UNIX 操作系统中的所有进程之间的关系呈现一个树形结构.除了进程 ID…
lienhua342014-10-05 1 进程控制三部曲概述 UNIX 系统提供了 fork.exec.exit 和 wait 等基本的进程控制原语.通过这些进程控制原语,我们即可完成对进程创建.执行和终止等基本操作.进程的控制可以划分为三部曲, • 第一部:fork 创建新进程. • 第二部:exec 执行新程序. • 第三部:exit 和 wait 处理终止和等待终止. 2 第一部:fork 创建新进程 在一个现有的进程中,我们可以通过调用 fork 函数来创建一个新进程, #includ…
lienhua342014-10-05 1 main 函数是如何被调用的? 在编译 C 程序时,C 编译器调用链接器在生成的目标可执行程序文件中,设置一个特殊的启动例程为程序的起始地址.当内核执行 C 程序时,在调用 main 前先调用这个特殊的启动例程,该启动例程从内核取得命令行参数和环境变量值. 2 共享库 共享库使得可执行文件中不再需要包含共用的库例程,而只需在所有进程都可引用的存储区中维护这种库例程的一个副本.程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链…
lienhua342014-10-02 1 进程的终止方式 进程的终止方式有 8 种,其中 5 种为正常终止,它们是 1. 从 main 返回. 2. 调用 exit. 3. 调用_exit 或_Exit. 4. 最后一个线程从其启动例程返回. 5. 最后一个线程调用pthread_exit. 另外三种为异常终止方式,它们是 1. 调用 abort. 2. 接到一个信号并终止. 3. 最后一个线程对取消请求做出响应. 2 exit 函数 有三个函数用于正常终止一个程序:_exit 和_Exit…
lienhua342014-08-23 UNIX 提供了两个函数 dup 和 dup2 用于复制一个现存的文件描述符. #include <unistd.h> int dup(int filedes); int dup2(int filedes, int filedes2); 返回值:若成功则返回新的文件描述符,如出错则返回-1. 由 dup 函数返回的文件描述符一定是当前可用文件描述符中的最小描述符.用 dup2 函数则可以通过参数 filedes2 指定目标文件描述符.如果filedes2…
lienhua342014-08-29 fcntl 函数可以改变已打开的文件的性质. #include <fcntl.h> int fcntl(int filedes, int cmd, ... /* int arg */); fcntl 函数有 5 种功能: 1. 复制一个现有的描述符(cmd=F_DUPFD). 2. 获取/设置文件描述符标志(cmd=F_GETFD 或F_SETFD). 3. 获取/设置文件状态标志(cmd=F_GETFL 或F_SETFL). 4. 获取/设置异步 I/…
lienhua342014-11-08 在进程控制三部曲中我们学习了进程的创建.终止以及获取终止状态等的进程控制原语.线程的控制与进程的控制有相似之处,在表 1中我们列出了进程和线程相对应的控制原语. 表 1: 进程原语和线程原语的比较 进程原语 线程原语 描述 fork pthread_create 创建新的控制流 exit pthread_exit 从现有的控制流中退出 waitpid pthread_join 从控制流中得到退出状态 atexit pthread_cleanup_push…
lienhua342014-10-29 1 信号的概念 维基百科中关于信号的描述是这样的: 在计算机科学中,信号(英语:Signals)是 Unix.类 Unix 以及其他 POSIX 兼容的操作系统中进程间通讯的一种有限制的方式.它是一种异步的通知机制,用来提醒进程一个事件已经发生.当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断.如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数. 关于这段描述,我们可以从中学习到下面几点关于信号…
lienhua342014-10-07 在文档“进程控制三部曲”中,我们提到 fork 函数创建子进程之后,通常都会调用 exec 函数来执行一个新程序.调用 exec 函数之后,该进程就将执行的程序替换为新的程序,而新的程序则从 main 函数开始执行. UNIX 提供了 6 种不同的 exec 函数供我们使用.它们的原型如下所示, #include <unistd.h>int execl(const char *pathname, const char *arg0, ... /* (cha…
lienhua342014 年 8 月 24 日 1. errno变量 文件 <errno.h> 中定义了符号 errno 以及可以赋予它的各种常量,这些常量都是以字符 E 开头.例如,若 errno 等于常量 EACCES,表示产生了权限问题(例如,没有打开所要求文件的足够权限). 当 UNIX 函数出错时,常常返回一个负值,而且将整型变量 errno 设置成含有附加信息的各个常量.例如,open 函数如果成功执行则返回一个非负文件描述符,如出错则返回 -1.在 open 出错时,有大约 1…
lienhua342014-11-24 1 取消线程 pthread 提供了pthread_cancel 函数用于请求取消同一进程中的其他线程. #include <pthread.h> int pthread_cancel(pthread_t tid); 返回值:若成功则返回0,否则返回错误编码 pthread_cancel 调用并不会立即终止目标线程,而只是向目标线程发出取消请求.调用线程不等待目标线程终止,在默认情况下,目标线程在取消请求发出以后还是继续运行的,直到目标线程到达某个取消点…
lienhua342014-10-15 ISO C 定义了 system 函数,用于在程序中执行一个命令字符串.其声明如下, #include <stdlib.h> int system(const char *cmdstring); system 函数在其实现中调用了 fork.exec 和 waitpid 函数.system 函数调用 fork 函数创建子进程,然后由子进程调用’/bin/sh -c cmdstring’ 来执行命令行参数 cmdstring,此命令执行完后便返回调用的进程…
lienhua342014-10-03 1 环境表和环境指针 在每个进程启动时,都会接到一张环境表.环境表是一个字符指针数组,其中每个指针包含一个以 null 结束的 C 字符串的地址.全局变量environ 则包含了该指针数组的地址, extern char **environ; 例如,图 1 显示了包含有 5 个环境字符串的环境表, 图 1: 含有 5 个环境字符串的环境表 2 环境变量 环境字符串的形式通常为,name=value. ISO C 定义了一个函数 getenv,用于获取环境变…
lienhua342014-11-09 1 线程属性概括 POSIX 线程的主要属性包括 scope 属性.detach 属性.堆栈地址.堆栈大小.优先级.在头文件 pthread.h 中定义了结构体pthread_attr_t 来记录线程的属性. 在创建线程的函数pthread_create 的第二个参数 attr 就是一个pthread_attr_t结构体的指针,通过该参数,我们可以控制新创建的线程的属性.如果 atrr参数为 NULL,表示创建一个默认属性的新线程. pthread_att…
lienhua342014-11-05 sigaction 函数跟 signal 函数一样,用于设置信号处理函数.此函数是用于取代 UNIX 早期版本使用的 signal 函数.UNIX 早期版本的 signal 函数在捕获到一个信号之后,就会自动将该信号的处理动作恢复为默认处理动作.于是,如果我们希望注册的信号处理函数长期生效,则需要在信号处理程序中再次调用 signal 函数注册一次.这样的操作太麻烦,而且在信号处理函数中再次调用 signal 注册信号处理函数之前可能又会产生该信号,而这个…
lienhua342014-11-03 1 信号传递过程 信号源为目标进程产生了一个信号,然后由内核来决定是否要将该信号传递给目标进程.从信号产生到传递给目标进程的流程图如图 1 所示, 图 1: 信号产生.传递到处理的流程图 进程可以阻塞信号的传递.当信号源为目标进程产生了一个信号之后,内核会执行依次执行下面操作, 1. 如果目标进程设置了忽略该信号,则内核直接将该信号丢弃. 2. 如果目标进程没有阻塞该信号,则内核将该信号传递给目标进程,由目标进程执行相对应操作. 3. 如果目标进程设置阻塞…
1. Future的使用 Future模式解决的问题是.在实际的运用场景中,可能某一个任务执行起来非常耗时,如果我们线程一直等着该任务执行完成再去执行其他的代码,就会损耗很大的性能,而Future接口就是Future的实现,它可以让当前线程将任务交给Future去执行,然后当前线程就可以去干别的事,知道耗时任务执行完成之后,当前线程直接获取结果即可.FutureTask的使用比较简单,只需要先实例化一个Callable对象,重写call方法,再创建一个FutureTask对象,将Callable…
 学习情况: 有关UNIX系统环境编程的学习时间用来非常长的时间.可是感觉效果还是不是太好,在中间经过了期末考试.用来非常长的时间用来学习专业课.就将该过程的学习放到了一边上,放假以后又回家造成了中间的学习时间打的非常散.又因为自己的水平还是十分有限的,所以该过程的学习效果感觉不太好.时间的观念在脑中还是不够强烈,整个过程中整体来说仅仅是在整体上了解了一个大概,实践还差的非常远. 学习期间博客: 1.UNIX环境编程初步认识--编程环境搭建 2.UNIX环境编程初步认识--文件和I/O 3.…