读apue部分笔记(二)

四、UNIX 中的系统数据文件

UNIX中的系统数据文件有/etc/passwd,/etc/group,/etc/shadow等。这些文件通常会被
应用程序读取或设置。/etc/shadow是一个专门用来存放用户密码的文件,当然了这个文件中的
密码都是加密后的密文。
newgrp是用来改变用户组的工具。
UNIX中的其他系统数据文件还有hosts,networks,protocols,services.
用来记录当前用户登录的文件是utmp,用来记录用户登录和退出的文件是wtmp。文件中的内容
一般是结构体utmp。who命令读的是utmp,last命令读的是wtmp。可以man utmp查看对应
的结构体。uname是用来打印系统信息的。
书中对时间和日期的介绍也很详细,需要注意的一点是,UNIX内核提供的时间接口函数返回的是
从UNIX元年开始计时的秒。

五、UNIX 进程环境

C语言中程序的执行是从main函数开始的,main的原型是int main(int argc,char *argv[])
参数argc表示命令行传入main的实际参数个数,argv表示传入main的实际参数列表,需要说明的
是在命令行中执行该函数时,函数名也是一个参数,所以即使没有实际参数,argc的值为1,
argv[0]表示函数名。
在main函数在执行前,会有一个启动例程会被编译器在编译源程序的链接过程中调用,编译后的可执行
程序会把这个例程作为执行的首地址,这个例程的作用是获取命令行参数的值和环境列表(每个进程的
执行都需要一个环境),并把这些值传给main,以便main可以顺利执行。通常这个例程是用汇编写的。
进程的结束可以是自愿的,比如调用return、exit等函数;也可以是被迫的,比如接收到信号,或调用
abort。进程结束也有很多事情要做,比如I/O的关闭和清理,进程结束后返回到os内核,让内核来运行
等。
通常一个C程序编译后会有:代码段(text)、初始化数据段、未初始化数据段(bss)、栈(stack)、
堆(heap),组成。代码段是用来存放程序指令的,是只读的,可以共享;初始化数据段是用来存放初
始化变量的;bss(block started by symbol)是用来存放在代码中没有初始化的变量的;栈是
用来存放 automatic variables(不会翻译,在看K&R时就不会翻译,但是没查)和每次函数被调
用时所需要的信息,比如被调用函数的返回地址和调用函数的环境等,新被调用的函数会在栈上为它的
automatic variables和 temporary variables分配空间,每个被调用的函数都会有一个自己
的 stack frame,所以各自函数互不干扰,这也是 C 语言递归函数的具体实现;堆是用来动态分配
内存的,比如malloc。用size工具可以查看一个可执行程序的各个段。
前面说了,每个进程都有一个环境,进程是可以通过getenv来获得相应的环境变量的值,当然,环境变量
的值也是可以设定的。
C语言中setjmp和longjmp用来实现在不同函数间实现跳转,setjmp用来设置要跳转的位置,longjmp
用来跳转到setjmp被调用的地方。C语言中goto只能在一个函数间跳转,二不能跨函数。setjmp和
longjmp一般用来处理异常的,想java中的try和catch一样。

六、UNIX 进程的控制

进程的控制包括进程的创建、程序的执行、进程的结束。
每个进程都会有一个唯一个进程id,每个进程只有一个id,这点和文件不同,比如一个文件在被共享的时候
可以有多个id。
一提到进程的创建就离不开fork,因为它是UNIX中创建进程的唯一方法。fork是吧父进程复制一份生成
子进程,在父进程中调用一次返回两次,父进程返回一次,子进程返回一次,在父进程中返回的值是用fork
创建的子进程的id,在子进程中返回的是0。根据fork的不同返回值父子进程可选择执行不同的代码。fork
在复制父进程时是按照copy on write来的,并且一般代码段是不会被复制的,由父子共享。请注意既然是
新生成一个进程,在fork后它俩谁先谁后执行,谁执行多长时间,就不一定了,这要看调度器了,但是父子
进程都从fork执行完后的指令开始执行。
父子进程共享文件的图:



sizeof测的是空间的大小,strlen测的是字符串的实际长度,他俩是不一样的。如果传给sizeof的是指针
则sizeof返回的是一个指针所占的空间,即一个指针占几个字节,如果传的是数组则返回的是数组的空间大
小,如果是一个字符串数组,则其返回值是字符串的实际长度+1,因为它把字符串的结束符也算上了,还有一点
是sizeof是宏,是在编译时计算的,也就是说sizeof只能计算在编译时空间是确定的对象;而strlen是函数
调用是运行时的是动态的。其实这我在看K&R时就看到了,但是看那本书时没做笔记,因此在看apue时看到了
就记下,这也说明了做笔记的重要性。
当子进程结束时内核会给父进程发送一个异步信号SIGCHLD。wait和waitpid的区别,wait会阻塞父进程直到
有一个子进程结束为止,waitpid会指定一个要等待的子进程,并且可根据选项来控制父进程是否阻塞。两个函数
返回的都是结束的子进程的id。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值