pread/pwrite
相当于 lseek,read/write ,只是pread/pwrite具有原子性,定位和读写操作不可中断
dup(fd); = fcntl(fd,F_DUPFD,0);
dup2(fd1,fd2); = close(fd2); fcntl(fd1,F_DUPFD,fd2);
减少磁盘读写次数: 延迟写
sync 交所有修改过的块缓冲区排入写队列
fsync 只对fd指定文件时行sync
fdatasync 类似fsync,但只是对数据部分,而fsync还会对文件属性进行更新
/dev/fd
打开文件/dev/fd/n等效于复制描述符
第四章:文件和目录
stat(const char *restrict pathname,struct stat *restrict buf);//返回与文件有关的信息结构。
fstat(int fd,struct stat *buf);
lstat(const char *restrict pathname,struct stat *restrict buf);//类似于stat,但是当命名的文件是一个符号链接时,
lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。
第五章:标准I/O库
对于ascii字符集,一个字符用一个字节表示,对于国际字符集,一个字符可用多个字节表示,标准io文件流可用于单字节或多字节("宽“)字符集。
流的定向(stream‘s orientation)决定了所读,写的字符是单字节还是多字节,当一个流最初被创建时,它并没有定向。如若在未定向的流上使用一个多字节io函数,
则将流的定向设置为宽定向的,如若在未定向的流上使用一个单字节io函数,则将流的定向设置为字节定向的,
freopen函数清除一个流的定向,fwide函数设置流的定向
int fwide(FILE *stream, int mode);
When mode is nonzero, the fwide() function first attempts to set
stream's orientation (to wide-character oriented if mode is greater
than 0, or to byte oriented if mode is less than 0). It then returns a
value denoting the current orientation, as above.
标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数。
标准I/O库提供了三种类型的缓冲
1、全缓冲 相关标准I/O函数通常调用malloc获得需使用的缓冲区。
flush(冲洗)函数fflush 一、在标准io库方面,flush(冲洗)意味着缓冲区中的内容写到磁盘上。
二、终端驱动程序方面,flush(刷清)表示丢弃已存储在缓冲区中的数据。
2、行缓冲。输入和输出遇到换行符时,标准io库执行io操作。当流涉及一个终端时(例如标准输入和标准输出),通常使用行缓冲。
3、不带缓冲。标准io库不对字符进行缓冲存储。例如fputs函数就是,标准出错流stderr通常是不带缓冲的,这就使得出错信息可以忙显示出来,而不管它们是否含有一个换行符。
void setbuf(FILE *fp,char *buf)
int setvbuf(FILE *fp,char *buf,int mode)
fp已打开的文件指针,buf为必须指向一个长度为BUFSIZ的缓冲区,为了关闭缓冲将buf设置为NULL
使用setvbuf,我们可以精确地指定所需要的缓冲类型,这里用mode参数实现的:
__IOFBF 全缓冲
__IOLBF 行缓冲
__IONBF 不带缓冲
如果指定一个不带缓冲的流,则忽略buf和size参数,如果该流是带缓冲的,而buf是NULL,则标准IO库将自动地为该流分配适当长度的缓冲区。
int fflush(FILE *fp);
作为一个特例,如若fp是NULL,则此函数将导致所有输出流被冲洗。
fopen freopen fdopen
int getc(FILE *fp); 可被实现为宏
int fgetc(FILE *fp); 不能实现宏,是一个函数,则可以把其地址作为参数传递。
int getchar(void); = getc(stdin)
不管是出错还是到达文件尾端,上面三个函数都返回同样的值,为了区分这两种不同的情况,必须调用ferror或feof。
在大多数实现中,为每个流在FILE对象中维持了两个标志:
1、出错标志 2、文件结束标志。
void clearerr(FILE *fp);清除这两个标志。
int ungetc(int c,FILE *fp); 压送回字符到流中
回头的字符不必一定是上一次读到的字符。不能回送EOF,但是当已经到达文件尾端时,仍可以回头一字符。下次读将返回该字符,再次读则返回EOF。
之所以能这样做的原因是一次成功的ungetc调用会清除该流的文件结束标志。
char *fgets(char *buf,int n,FILE *fp);
char *gets(char *buf);
fgets,必须指定缓冲区的长度n,此函数一直读到下一个换行符为止,但是不超过n-1个字符,读入的字符被卷入缓冲区。该缓冲区心null字符结尾,如若该行(包括最后一个换行符)的字符超过n-1,则fgets只返回一个不完整的行,但是,缓冲区总是以null字符结尾。对fgets的下一次调用会继续读该行。
gets是一个不推荐使用的函数,因不能指定缓冲区的长度,可能造成缓冲区溢出。
gets与fgets的另一个区别是,gets并不将换行符存入缓冲区中。
int fputs(char *str,FILE *fp);
int puts(char *str);
fputs将一个以null符终止的字符串写到指定的流中,尾端的终止符null不写出。
puts将一个以null符终止的字符串写到标准输出,终止符不写出,但是,puts然后又将一个换行符写到标准输出。
fread fwrite
ftell fseek
ftello fseeko 用off_t代替long修饰偏移量
输出转换说明
%[flags][fldwidth][precision][lenmodifier]convtype
flags: 1.-左对齐 2.+显示带符号 3.(空格)如果第一个不是符号,则在其前面加上一个空格 4.#进制 5.0添加前导
fldwidth:最小字段宽度
precision:最少输出数字位数(整数)、小数位数(浮点数)、最大字符数(字符串)。精度是一个句点(.),后接一个可选的非负十进制整数或一个星号(*)。
宽度和精度都可以为*.
lenmodifier:说明参数长度
hh:char
h:short
l:long
ll:long long
j:intmax_t
z:size_t
t:ptrdiff_t
L:long double
convtype:
d,i
o
u
x 十六进制
f,F double精度浮点数
e,E 指数格式的double
g,G 解释为f,F,e或E,取决被转换的值
A,a 十六进制指数格式的double
c
s
p
n 将到目前为止,所写的字符数写入到指针所指向的无符号整型中。
%
临时文件:
char *tmpnam(char *ptr);
FILE *tmpfile(void);
使用fgets和fputs通常需要复制两次数据:一次是在内核和标准io缓冲之间(当调用read和write时),第二次是在标准io缓冲区和用户程序中的行缓冲区之间。
快速io库其方法是使读一行的函数返回指向该行的指针,而不是将该行复制到另一个缓冲区中。
第六章:系统数据文件和信息
历史原因,口令文件存储在/etc/passwd中,而且是一个ASCII文件,每一行包含系统支持的各字段,字段之间用冒号分隔。eg:
root:x:0:0:root:/root:/bin/bash
口令用(x)占位符表示,实际存储在另一个位置。
某些系统提供了vipw命令,允许管理员使用该命令编辑口令文件。vipw命令串行化对口令文件所做的更改,并且确保所做的更改与其他相关文件一致。
struct passwd *getpwnam(const char *name);
struct passwd *getpwuid(uid_t uid);
getpwuid函数由ls程序使用,它将i节点中的数值用户id映射为用户登录名,在键入登录名时,getpwnam函数由login程序使用。
查看整个口令文件,有以下三个函数:
struct passwd *getpwent(void);
void setpwent(void);
void endpwent(void);
加密口令是经意向加密算法处理过的用户口令副本,因为单向,所以不能从加密口令推测到原来的文本口令。
猜测文本口令单向加密算法转换成加密形式,再和加密口令比较,为防止这,把加密口令放到称为阴影口令(shadow password)的文件中。
int gettimeofday(struct timeval *tv, struct timezone *tz); //微秒级的
time_t time(time_t *t); //秒级
第七章 进程环境
进程终止:
正常终止:1、从main返回;2、调用exit;3、调用_exit或_Exit;4、最后一个线程从其启动例程返回;5、最后一个线程对取消请求做出响应
异常终止:6、调用abort;7、接到一个信号并终止;8、最后一个线程对取消请求做出响应。
_exit/_Exit立即进入内核,exit则先执行一些清理处理(包括调用执行各终止处理程序,关闭所有标准io流等)再进入内核。
a、 三个exit函数被调用时不带终止状态;b、main执行没有返回值的return语句;c、main没有声明返回类型为整型,则该进程的终止状态是未定义的。
但是,若main的返回类型是整型,并且main执行到最后一条语句时返回(隐式返回),那么该进程的终止状态是0。
在main函数中exit(0) 等价于 return(0)
atexit函数
按照iso c的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用。我们称这些函数为终止处理程序(exit handler),并调用atexit函数来登记这些函数。
int atexit(void (*function)(void));
exit调用终止处理程序顺序和登记顺序相反。同一函数登记多次,则也会被调用多次。
程序调用exec函数族中的任一函数,则将清除所有已安装的终止处理程序。
注意:内核使程序执行的唯一方法是调用一个exec函数。
每个程序都会接收到一张环境表,与参数表一样,环境表也是一个字符指针数组。全局变量environ则包含了该指针数组的地址:
extern char **environ;
malloc 初始值不确定
calloc 初始为0
realloc
在C中,goto语句是不能跨越函数的,而执行跨越函数类跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在深层嵌套调用中的出错情况是非常有用的。
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env,int val);
第八章 进程控制
pid为0的进程通常是调度进程,常常被称为交换进程,是内核的一部分。
pid为1的进程init,
pid为2的进程是页守护进程,负责支持虚拟存储系统的分页操作。
strlen:计算不包含终止null字节的字符串长度,是一个函数调用
sizeof:计算包括终止null字节的缓冲区长度,空间已知,所以sizeof在编译时计算缓冲区长度。
fork:父子进程共享一个文件表项。父子进程各自关闭不使用的文件描述符,不相互干扰,这是网络服务进程中经常使用的。
出于安全性方面的考虑,有些人要求在搜索路径PATH中决还要包括当前目录。
exec l:list v:vector
函数execl,execlp,execle要求将新程序的每个命令行参数都说明为一个单独的参数,这种参数表以空指针结尾。
函数execv,execvp,execve则应先构造一个指向各参数的指针数组,然后将该数组地址作为这三个函数的参数。
execlp,execvp以文件名作参数,其余4个以路径名作参数。
execle,execve可以传递一个指向环境表字符串指针数组的指针,其余四个函数则使用调用进程中的environ变量为新程序复制现有的环境。
每个系统对参数表和环境表的总长度都有个限制。这种限制是由ARG_MAX给出的。
我们可以将argv[0]设置为任何字符串,当login命令执行shell时就是这样做的。
全局变量char **environ包括PATH等很多环境变量。
解释器文件(interpreter file),其起始行的形式是: #! pathname[optional-argument]
pathname通常是绝对路径名。
int system(const char *cmdstring); ISO C定义了system函数,但是其操作对系统的信赖性很强,在unix中,system总是可用的。
system在实现中调用了fork,exec和waitpid。
进程会计(process accounting):通过acct函数启用禁用功能,每当进程结束时内核就写一个会计记录。
int setpgid(pid_t pid, pid_t pgid);
setpgid() sets the PGID of the process specified by pid to pgid. If
pid is zero, then the process ID of the calling process is used. If
pgid is zero, then the PGID of the process specified by pid is made the
same as its process ID.
setpgid函数将pid进程的进程组id设置为pgid。如果这两个参数相等,则由pid指定的进程变成进程组组长。如果pid是0,则使用调用者的进程id。
另外,如果pgid为0,则由pid指定的进程id将用作进程组id。
dup(fd); = fcntl(fd,F_DUPFD,0);
dup2(fd1,fd2); = close(fd2); fcntl(fd1,F_DUPFD,fd2);
减少磁盘读写次数: 延迟写
sync 交所有修改过的块缓冲区排入写队列
fsync 只对fd指定文件时行sync
fdatasync 类似fsync,但只是对数据部分,而fsync还会对文件属性进行更新
/dev/fd
打开文件/dev/fd/n等效于复制描述符
第四章:文件和目录
stat(const char *restrict pathname,struct stat *restrict buf);//返回与文件有关的信息结构。
fstat(int fd,struct stat *buf);
lstat(const char *restrict pathname,struct stat *restrict buf);//类似于stat,但是当命名的文件是一个符号链接时,
lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。
第五章:标准I/O库
对于ascii字符集,一个字符用一个字节表示,对于国际字符集,一个字符可用多个字节表示,标准io文件流可用于单字节或多字节("宽“)字符集。
流的定向(stream‘s orientation)决定了所读,写的字符是单字节还是多字节,当一个流最初被创建时,它并没有定向。如若在未定向的流上使用一个多字节io函数,
则将流的定向设置为宽定向的,如若在未定向的流上使用一个单字节io函数,则将流的定向设置为字节定向的,
freopen函数清除一个流的定向,fwide函数设置流的定向
int fwide(FILE *stream, int mode);
When mode is nonzero, the fwide() function first attempts to set
stream's orientation (to wide-character oriented if mode is greater
than 0, or to byte oriented if mode is less than 0). It then returns a
value denoting the current orientation, as above.
标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数。
标准I/O库提供了三种类型的缓冲
1、全缓冲 相关标准I/O函数通常调用malloc获得需使用的缓冲区。
flush(冲洗)函数fflush 一、在标准io库方面,flush(冲洗)意味着缓冲区中的内容写到磁盘上。
二、终端驱动程序方面,flush(刷清)表示丢弃已存储在缓冲区中的数据。
2、行缓冲。输入和输出遇到换行符时,标准io库执行io操作。当流涉及一个终端时(例如标准输入和标准输出),通常使用行缓冲。
3、不带缓冲。标准io库不对字符进行缓冲存储。例如fputs函数就是,标准出错流stderr通常是不带缓冲的,这就使得出错信息可以忙显示出来,而不管它们是否含有一个换行符。
void setbuf(FILE *fp,char *buf)
int setvbuf(FILE *fp,char *buf,int mode)
fp已打开的文件指针,buf为必须指向一个长度为BUFSIZ的缓冲区,为了关闭缓冲将buf设置为NULL
使用setvbuf,我们可以精确地指定所需要的缓冲类型,这里用mode参数实现的:
__IOFBF 全缓冲
__IOLBF 行缓冲
__IONBF 不带缓冲
如果指定一个不带缓冲的流,则忽略buf和size参数,如果该流是带缓冲的,而buf是NULL,则标准IO库将自动地为该流分配适当长度的缓冲区。
int fflush(FILE *fp);
作为一个特例,如若fp是NULL,则此函数将导致所有输出流被冲洗。
fopen freopen fdopen
int getc(FILE *fp); 可被实现为宏
int fgetc(FILE *fp); 不能实现宏,是一个函数,则可以把其地址作为参数传递。
int getchar(void); = getc(stdin)
不管是出错还是到达文件尾端,上面三个函数都返回同样的值,为了区分这两种不同的情况,必须调用ferror或feof。
在大多数实现中,为每个流在FILE对象中维持了两个标志:
1、出错标志 2、文件结束标志。
void clearerr(FILE *fp);清除这两个标志。
int ungetc(int c,FILE *fp); 压送回字符到流中
回头的字符不必一定是上一次读到的字符。不能回送EOF,但是当已经到达文件尾端时,仍可以回头一字符。下次读将返回该字符,再次读则返回EOF。
之所以能这样做的原因是一次成功的ungetc调用会清除该流的文件结束标志。
char *fgets(char *buf,int n,FILE *fp);
char *gets(char *buf);
fgets,必须指定缓冲区的长度n,此函数一直读到下一个换行符为止,但是不超过n-1个字符,读入的字符被卷入缓冲区。该缓冲区心null字符结尾,如若该行(包括最后一个换行符)的字符超过n-1,则fgets只返回一个不完整的行,但是,缓冲区总是以null字符结尾。对fgets的下一次调用会继续读该行。
gets是一个不推荐使用的函数,因不能指定缓冲区的长度,可能造成缓冲区溢出。
gets与fgets的另一个区别是,gets并不将换行符存入缓冲区中。
int fputs(char *str,FILE *fp);
int puts(char *str);
fputs将一个以null符终止的字符串写到指定的流中,尾端的终止符null不写出。
puts将一个以null符终止的字符串写到标准输出,终止符不写出,但是,puts然后又将一个换行符写到标准输出。
fread fwrite
ftell fseek
ftello fseeko 用off_t代替long修饰偏移量
输出转换说明
%[flags][fldwidth][precision][lenmodifier]convtype
flags: 1.-左对齐 2.+显示带符号 3.(空格)如果第一个不是符号,则在其前面加上一个空格 4.#进制 5.0添加前导
fldwidth:最小字段宽度
precision:最少输出数字位数(整数)、小数位数(浮点数)、最大字符数(字符串)。精度是一个句点(.),后接一个可选的非负十进制整数或一个星号(*)。
宽度和精度都可以为*.
lenmodifier:说明参数长度
hh:char
h:short
l:long
ll:long long
j:intmax_t
z:size_t
t:ptrdiff_t
L:long double
convtype:
d,i
o
u
x 十六进制
f,F double精度浮点数
e,E 指数格式的double
g,G 解释为f,F,e或E,取决被转换的值
A,a 十六进制指数格式的double
c
s
p
n 将到目前为止,所写的字符数写入到指针所指向的无符号整型中。
%
临时文件:
char *tmpnam(char *ptr);
FILE *tmpfile(void);
使用fgets和fputs通常需要复制两次数据:一次是在内核和标准io缓冲之间(当调用read和write时),第二次是在标准io缓冲区和用户程序中的行缓冲区之间。
快速io库其方法是使读一行的函数返回指向该行的指针,而不是将该行复制到另一个缓冲区中。
第六章:系统数据文件和信息
历史原因,口令文件存储在/etc/passwd中,而且是一个ASCII文件,每一行包含系统支持的各字段,字段之间用冒号分隔。eg:
root:x:0:0:root:/root:/bin/bash
口令用(x)占位符表示,实际存储在另一个位置。
某些系统提供了vipw命令,允许管理员使用该命令编辑口令文件。vipw命令串行化对口令文件所做的更改,并且确保所做的更改与其他相关文件一致。
struct passwd *getpwnam(const char *name);
struct passwd *getpwuid(uid_t uid);
getpwuid函数由ls程序使用,它将i节点中的数值用户id映射为用户登录名,在键入登录名时,getpwnam函数由login程序使用。
查看整个口令文件,有以下三个函数:
struct passwd *getpwent(void);
void setpwent(void);
void endpwent(void);
加密口令是经意向加密算法处理过的用户口令副本,因为单向,所以不能从加密口令推测到原来的文本口令。
猜测文本口令单向加密算法转换成加密形式,再和加密口令比较,为防止这,把加密口令放到称为阴影口令(shadow password)的文件中。
int gettimeofday(struct timeval *tv, struct timezone *tz); //微秒级的
time_t time(time_t *t); //秒级
第七章 进程环境
进程终止:
正常终止:1、从main返回;2、调用exit;3、调用_exit或_Exit;4、最后一个线程从其启动例程返回;5、最后一个线程对取消请求做出响应
异常终止:6、调用abort;7、接到一个信号并终止;8、最后一个线程对取消请求做出响应。
_exit/_Exit立即进入内核,exit则先执行一些清理处理(包括调用执行各终止处理程序,关闭所有标准io流等)再进入内核。
a、 三个exit函数被调用时不带终止状态;b、main执行没有返回值的return语句;c、main没有声明返回类型为整型,则该进程的终止状态是未定义的。
但是,若main的返回类型是整型,并且main执行到最后一条语句时返回(隐式返回),那么该进程的终止状态是0。
在main函数中exit(0) 等价于 return(0)
atexit函数
按照iso c的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用。我们称这些函数为终止处理程序(exit handler),并调用atexit函数来登记这些函数。
int atexit(void (*function)(void));
exit调用终止处理程序顺序和登记顺序相反。同一函数登记多次,则也会被调用多次。
程序调用exec函数族中的任一函数,则将清除所有已安装的终止处理程序。
注意:内核使程序执行的唯一方法是调用一个exec函数。
每个程序都会接收到一张环境表,与参数表一样,环境表也是一个字符指针数组。全局变量environ则包含了该指针数组的地址:
extern char **environ;
malloc 初始值不确定
calloc 初始为0
realloc
在C中,goto语句是不能跨越函数的,而执行跨越函数类跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在深层嵌套调用中的出错情况是非常有用的。
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env,int val);
第八章 进程控制
pid为0的进程通常是调度进程,常常被称为交换进程,是内核的一部分。
pid为1的进程init,
pid为2的进程是页守护进程,负责支持虚拟存储系统的分页操作。
strlen:计算不包含终止null字节的字符串长度,是一个函数调用
sizeof:计算包括终止null字节的缓冲区长度,空间已知,所以sizeof在编译时计算缓冲区长度。
fork:父子进程共享一个文件表项。父子进程各自关闭不使用的文件描述符,不相互干扰,这是网络服务进程中经常使用的。
出于安全性方面的考虑,有些人要求在搜索路径PATH中决还要包括当前目录。
exec l:list v:vector
函数execl,execlp,execle要求将新程序的每个命令行参数都说明为一个单独的参数,这种参数表以空指针结尾。
函数execv,execvp,execve则应先构造一个指向各参数的指针数组,然后将该数组地址作为这三个函数的参数。
execlp,execvp以文件名作参数,其余4个以路径名作参数。
execle,execve可以传递一个指向环境表字符串指针数组的指针,其余四个函数则使用调用进程中的environ变量为新程序复制现有的环境。
每个系统对参数表和环境表的总长度都有个限制。这种限制是由ARG_MAX给出的。
我们可以将argv[0]设置为任何字符串,当login命令执行shell时就是这样做的。
全局变量char **environ包括PATH等很多环境变量。
解释器文件(interpreter file),其起始行的形式是: #! pathname[optional-argument]
pathname通常是绝对路径名。
int system(const char *cmdstring); ISO C定义了system函数,但是其操作对系统的信赖性很强,在unix中,system总是可用的。
system在实现中调用了fork,exec和waitpid。
进程会计(process accounting):通过acct函数启用禁用功能,每当进程结束时内核就写一个会计记录。
int setpgid(pid_t pid, pid_t pgid);
setpgid() sets the PGID of the process specified by pid to pgid. If
pid is zero, then the process ID of the calling process is used. If
pgid is zero, then the PGID of the process specified by pid is made the
same as its process ID.
setpgid函数将pid进程的进程组id设置为pgid。如果这两个参数相等,则由pid指定的进程变成进程组组长。如果pid是0,则使用调用者的进程id。
另外,如果pgid为0,则由pid指定的进程id将用作进程组id。