系统调用:内核的接口。
/etc/passwd中存放登录名,由七个字段组成。
Unix文件系统:目录的起点为根(/) 目录是包含多个目录项的文件
点(.)指向当前目录 点点(..)指向父目录。
以斜杠(/)开头的是绝对路径 否则是相对路径。
$是shell打印的提示符。
文件描述符:
当运行一个新程序时候,所有的shell都为其打开三个文件描述符:标准输入、标准输出、标准出错。默认指向终端。
STDIN_FILENO STDOUT_FILENO在头文件<unistd.h>头文件中,指定了标准输入和标准输出的文件描述符。在posix中,值是0和1
不用缓冲的IO:
open read write lseek close
不带缓冲的IO 自己选择一个内存空间来作为中间保存 open read write lseek close
带缓冲的IO(标准IO):无需担心缓冲区多大 printf putc getc
进程ID:标识唯一的一个进程(非负整数)。
getpid()
进程控制:fork exec waitpid
用户标识:
用户ID 组ID
信号:通知进程已经发送某种情况的一种技术。
时间:日历时间和进程时间。
度量一个进程的时间:
1.时钟时间
2.用户CPU时间
3.系统CPU时间
调用信号的实例: 中断健 ctrl+c 和 kill指令 都是向进程发送信号。
系统调用和库函数调用区别:
第三章:文件IO
open函数
mode:新文件访问权限。
create函数:创建一个新文件
close函数:关闭文件
lseek函数:显式的为一个打开文件设置偏移量。这样读取不用从头开始
read函数:从打开文件中读取数据
write函数:向打开文件中写数据
多个进程可以打开同一个文件,都有自己的文件表项目,都有自己的偏移量。
多个进程读同一个文件正常,但是当多个进程写一个文件的时候就可能会有错误。
原子操作pread和pwrite
dup函数和dup2函数:复制现有的文件描述符。
延迟写:内核先把数据写入缓冲区,再写入磁盘
fcntl函数:可以改变已经打开的文件的属性。
ioctl函数
第四章:
stat函数
struct stat的成员:
文件分类:
设置用户id和设置组id:
实际用户id和有效用户id的区别:
实际用户ID和实际用户组ID:标识我是谁。也就是登录用户的uid和gid,比如我的Linux以simon登录,在Linux运行的所有的命令的实际用户ID都是simon的uid,实际用户组ID都是simon的gid(可以用id命令查看)。
有效用户ID和有效用户组ID:进程用来决定我们对资源的访问权限。一般情况下,有效用户ID等于实际用户ID,有效用户组ID等于实际用户组ID。当设置-用户-ID(SUID)位设置,则有效用户ID等于文件的所有者的uid,而不是实际用户ID;同样,如果设置了设置-用户组-ID(SGID)位,则有效用户组ID等于文件所有者的gid,而不是实际用户组ID。
suid 就是ll命令下 x的权限为s 这样有效用户id就是这个文件拥有者的id 就是说 别的用户和这个文件的拥有者有一样的权限都是执行。
access测试其文件权限
umask:为进程设置文件模式创建屏蔽字
chmod 更改现有文件的访问权限:
S_ISVTX:粘着位
chown改变用户ID和组ID
truncate:文件截取
st_nlink:也就是硬链接才有
link函数创建一个指向该文件的链接:
unlink:删除现有的目录项:
rename:对文件重命名
symlink:创建符号链接
0
打开符号链接:
文件时间:
更改修改时间:
mkdir:创建目录:
读目录:
修改当前工作目录:
文件访问权限:
第五章:标准IO库
理解的缓冲:减少write的次数 如果缓冲区是1024字节 要把2048字节的行写到标准输出,则要进行两次write系统调用。这并没有限制输出输入的行的长度。
标准IO库:基于流的
fwide:设置流的定向
缓冲分类:全缓冲 行缓冲 不带缓冲
更改缓存
打开标准流fopen
其type:
fclose
一次读一个字符:
输出函数
每次输入一行:
每次输出一行:
二进制IO操作
格式化输出:
fileno:根据文件指针获得文件描述符。
理解的缓冲:减少write的次数 如果缓冲区是1024字节 要把2048字节的行写到标准输出,则要进行两次write系统调用。这并没有限制输出输入的行的长度。
临时文件:
第六章:系统数据文件和信息
passwd结构的属性:
根据用户名获得相关信息
查看口令文件:
getpwent返回的口令文件中的下一个记录项
阴影口令的成员:
访问阴影口令文件:
group成员:
查看组名
附属组id
还经常用的文件
uname 与主机和OS相关的信息。
第七章:
atexit函数:可以登记多个函数,这些函数将由exit自动调用
执行程序时,调用exec的进程可以将命令行参数传递给新程序。
c程序由一下部分组成:
1.正文段。可共享。
2.初始化数据段。
3.未初始化数据:BSS段
4.堆
5.栈
动态分配函数:
替代的存储空间分配程序:
获得环境变量:
函数跳转:
env一般定义为全局变量。
开始的时候用setjmp记录信息
然后再用kongjmp调到原来的函数
其寄存器的值不确定是否变回来原来的值。
#ifdef #endif是C语言的条件编译。
一般情况下,源程序中所有的行都参加编译。但有时希望对其中一部分内容只在满足一定条件下才进行编译,即对一部分内容指定编译条件,这就是“条件编译”(conditional compile)。
#ifdef的一般形式:
#ifdef宏名
//语句段
#endif
作用:如果在此之前已定义了这样的宏名,则编译语句段。
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
第八章:进程控制
进程的唯一标识:进程id
id=2 页守护进程 负责虚拟内存的分页。
子进程获得父进程的数据空间和堆和栈的副本。并不共享这些,只共享正文段。
子进程和父进程执行顺序不确定
strlen和sizeof区别:
子进程也会复制父进程的缓冲区:
子进程和父进程共享文件偏移量 所以可以同时写到一个文件
fork失败的原因:
vfork:exit 或者 exec前面 在父进程的地址空间运行 也就是共享数据,同时 子进程先执行。
进程有5种正常终止和3种异常终止:
孤儿进程的处理:
僵死进程:
init收养的进程不会变成僵死进程:
可以理解为:如果有子进程终止,wait结束。否则wait会使调用者阻塞,直到有一个子进程终止,释放子进程,继续运行。
参数statloc:终止状态的指针。
waitpid等待某个pid的子进程终止,其他的不进程结束 程序不结束
当进程调用exec函数,进程执行的程序完全替换为新程序,新程序从main函数开始执行。用磁盘上的新程序替换了当前进程的正文段数据段、堆 栈段
设置实际用户id和有效用户id
设置实际组id和有效组id
解释器文件:文本文件 起始行是以下开头。
解释器:由pathname指定。
注意:exec的第一个参数
system:相当于先fork一个子进程,然后再exec执行/bin/sh脚本 的指令
nice值 用来指定进程调度优先级:
第九章:进程关系
进程组id:每一个进程组有一个唯一的进程组id。进程组id是一个正整数。
第十章:信号
对信号的处理:
1.忽略
2.捕捉
3.执行系统默认动作。
信号机制函数
func参数:SIG_IGN忽略信号 SIG_DFL执行默认动作 当指定函数地址,信号发生,调用此函数,捕捉信号。
十一章:线程
线程id比较:
线程可以获得自身线程id
每个进程只有一个控制线程。
线程退出:
任何线程可以调用pthread_join来获得一个线程退出时候的状态
多线程之间的同步问题:
比如一个++操作:需要三步:
一个操作需要多个周期 ,所以有数据不一致性问题。
多线程的5种基本同步方式:互斥量、读写锁、条件变量、自旋锁、屏障。
互斥量的本质是锁。
初始化互斥量 和加锁 解除锁
读写锁:
条件变量:线程的一种同步机制。
条件变量初始化:
自旋锁:
屏障允许线程等待,直到所有的合作线程都到达某一点,然后从该点继续执行。pthread_join就是一种屏障。
十二章:
线程初始化线程属性:
设置线程属性:
其线程属性包括哪些:
对线程栈属性进行管理:
同步属性:
互斥量属性
共享属性的修改
健壮属性的修改:
十三章:守护进程 daemon
守护进程程序需要遵守的一些规则。1-6
守护进程会将其错误等输出到日志
十四章:高级IO
IO多路转接:
将一个给定的文件映射到一个存储区域中,
映射存储区位于堆和栈之间,各种实现可能不同。
十五章:进程间通信
方式:管道 FIFO 消息队列 信号量 共享存储
管道:半双工(数据只能在一个方向上流动) 只能在具有公共组选的两个进程之间使用。
popen和pclose
协同进程
Unix目录树:每个盘有自己的unix树 之后一起连接起来。每棵树都有自己的根目录