QUESTION:
1. 每打开一个文件流,都会分配独立的1024byte行 及 4k 全缓 的缓冲区吗?
每打开一个文件流C库都会分配独自的全缓存区(文件打开默认是全缓存方式,除
了stdout、stdint/stderr),如果修改行缓存模式,有两种方式,1:C库自
动分配行缓存,自己创建行缓存空间给文件。
2. 栈的增长方向:
大部分人选择用在main函数中连续定义栈空间这种方式来判断栈是往递减方向增长的,
很遗憾,这种方式不大正确。
void func2()
{
int i_2 = 0;
fprintf(stdout,"i_2 = %p\n",&i_2);
}
void func1()
{
int i_1 = 0;
fprintf(stdout,"i_1 = %p\n",&i_1);
func2();
}
int main(){
int a;
int b;
int *c = (int*)malloc(sizeof(int));
int *d = (int*)malloc(sizeof(int));
fprintf(stdout,"a = %p, b = %p, c = %p, d = %p\n",&a,&b,c,d);
func1();
return 0;
}
运行结果:
a = 0x7ffd7e35317c, b = 0x7ffd7e353180, c = 0x5627f3c75670, d = 0x5627f3c75690
i_1 = 0x7ffd7e353144
i_2 = 0x7ffd7e353124
LEARNING NOTE:
3. 父子进程不同处:
- 进程ID
- fork返回值
- 父进程ID
- 进程运行时间
- 闹钟(定时器)
4. 读时共享,写时复制:
0-3g用户空间是独立的,但是如果修改0-3g空间内的变量,原先的值会复制一份(会映射出自
己的相应物理地址空间。),如果只是读操作,则会和父进程公用物理空间,但虚拟地址空间还是独享的。
####5. 当进程终止时,操作系统的隐式回收机制会:
- 关闭所有文件描述符 - 释放用户口空间分配的内存,内核的PCB仍存
在,其中保存该进程的退出状态。(正常终止->退出值;异常终止->终止信号)。
6. 使用wait函数:
传出参数status来保存进程的退出状态,借助宏函数来进一步判断进程终止的具体原因。
- 宏函数可分为如下三组:(需要记忆前两组)
- WIFEXITED(status)为非0->进程正常结束
WEXITSTATUS(status)如上宏为真,使用此宏->获取进程退出状态(exit的参数) - WIFSIGNALED(status)为非0 ->进程异常终止
WTERMSIG(status) 如上宏为真,使用此宏->取得使进程终止的那个信号的编号。
- WIFEXITED(status)为非0->进程正常结束
7. 进程通信方式:
- 管道(使用最简单)
- 信号(开销最小)
- 共享映射区(内存)(无血缘关系)
- 本地套接字(最稳定)
8. 父子进程内核区(3G-4G):
虚拟空间地址也是独立的,但是映射的物理地址是相同的(部分相同,除了pcb等)。
9. linux下文件分类:
- 占用磁盘存储的文件:
- - 文件
- d 目录
- l 符号链接
- 伪文件:(不占用磁盘存储)
- s 套接字
- b 块设备
- c 字符设备
- p 管道 (本质是个___伪文件___,实则为___内核缓存区___,默认是4k(可调整) 查看linux命令ulimit -a )
10. 管道的局限性:
- pipe():
- 数据自己读不能自己写。
- 数据一旦被读走,便不在管道中存在,不可反复读取)。
- 由于管道采用半双工通信方式,因此,数据只能在一个方向上流动。
- 只能在有___公共祖先的进程间使用管道___。
- 只有写端没有读端,写数据操作会报错,系统保护数据丢失(丢包)机制。
- 只有读端没有写端,读数据操作,如果缓冲区(默认4k)有数据,则会读出数据,没有数据,读出个数为0
- 读写端都有,只写操作,写满时,再写时该操作(写操作)会阻塞等待。
- 读写端都有,只读操作,有数据,则会读出,没有则读出个数为0
11. 守护进程创建:
- 创建子进程 fork
- 子进程创建新会话 setsid()
- 改变进程的工作目录 chdir()
- 指定文件掩码 umask()
- 将0/1/2重定向 /dev/null dup2()
- 守护进程主逻辑
- 退出(一般不用)。
12. 关于exec函数的注意:
- 执行exec函数族,会替换原本进程的用户空间(新建一个子进程),并且执行完毕将不会反会(调用exec函数的程序中,在exec函数后面的代码不会再执行)。
13. 关于pthread_join():
- 一般这个函数在主控线程中执行。
14. pthread有两种状态:
- 可结合的(joinable)线程默认创建为可结合态
当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)。只有当你调用了pthread_join之后这些资源才会被释放。,
- 分离的(detached)
这些资源在线程函数退出时或pthread_exit时自动会被释放。
- 使用pthread_detach函数可以设置线程为分离态)
15. pthread_create():
- 第二个参数可以设置线程属性。线程状态(两种:可结合态、分离态)、线程大小、线程栈警戒区大小…等。
16. linux中所有锁,都是___建议锁(包括互斥锁)____(不强制),如果不按照规则也能操作。(可以不按规则)。
17. pthrad_mutex函数族:
- 加锁,就是对mutex做减操作。
- 解锁,就是对mutex做加操作。
- mutex的值只会是0或1
18. 线程同步与互斥(线程间通信):
- 互斥:就是大家可以抢,但如果有人抢到了,另一个人必须等他执行完操作后,再抢。有可能出现有人一直抢不到的情况。
- 用完锁之后,一定要___立即解锁__,锁的"粒度"越小越好。__
19. 条件变量:
- 条件变量本事不是锁,一般和互斥锁一起使用。
- pthread_cond_wait()
20. 信号:
- 信号都有的共性:
简单
不能携带大量信息
满足某个特设条件才发送。
- 不管是___软中断(软件做的中断),还是硬中断(硬件做的中断),接收到信号,都会立即停止___
- 每个进程收到的所有信号,都是油内核负责发送的,内核处理。
- 进程A想要给进程B发信号:进程A先给内核发信号,然后内核再给进程B发信号。
21. 产生信号的方式(5种):
1. 按键产生,如:Ctrl+c Ctrl+z Ctrl+\
2. 系统调用产生,如:kill、raise、abort
3. 软件条件产生,如:定时器alarm
4. 硬件异常产生,如:非法访问内存(段错误)、除0(浮点数例外)、内存对齐出错(总线错误)
5. 命令产生,如:kill命令。
22. 递达&未决信号集:
- 递达:递达并且到达进程。
- 未决:产生和递达之间的状态,主要由于阻塞(屏蔽)导致该状态。
23. 信号的处理方式:
1. 执行默认动作
2. 忽略(丢弃)
3. 捕捉(调用,用户处理函数)
24. scanf函数族:
1. 遇到空格都会结束函数
2. 需要接受空格时,需要用___get___函数族