《高级UNIX编程》读书笔记

    技术2022-06-30  79

    2011年1月7日

    第一章 基本概念

    perror是与 errno相关的,它会查阅errno从而打印出错误号对应的消息。很有用哈。

    2011年1月9日

    不知不觉就看到第5章了。

    关于全局环境变量:environ

    #include <iostream> extern char **environ; //外部的全局环境变量 int main() { for(int i = 0; environ[i] != NULL; i++) std::cout << environ[i] <<std::endl; }

    可以打印出shell的环境变量

    利用标准C函数获得环境变量:

    char* getenv(const char *var)

    putenv(char *string); // 改变或加入环境变量,形如name=value形式

    setenv(const char *var, const char *val, int overwrite );

    unsetenv(const char *var);//删除环境变量

    exec系统调用 :

    exec从指定程序重新初始化进程,但fork不是,fork是复制了父进程得来的。调用exec时IO中未刷新的缓冲将废弃。

    1.原来任何用atexit注册的函数都被出取消,因为已经没有代码了

    2.共享内存段失效被断开,因为连接点已失效

    3.关闭POSIX信号量,但System V信号量不受影响

    4.如果进程已经安排捕获信号,而被委派捕获信号的指令已经消失,那么信号将被重置为默认动作

    fork系统调用:

    fork的进程复制了父进程的指令,用户数据,和系统数据段。

    没继承的:

    1.子进程ID与父进程ID不同

    2.如果父进程是多线程,那么子进程中只有执行fork线程的那个线程

    3.子进程的累计时间被重置为零,因为它处于生存期的开始

    注:子进程复制了父进程打开的文件描述符,它们共享文件偏移,如果子进程用 lseek改变了文件指针,父进程同样受到影响。

    关于sysconf:

    sysconf可以获得很多系统的参数,如fd的最大个数等

    exit系统调用 :

    _exit和_Exit 

    两者等同,都是不做清理便终止进程。不会调用atexit()注册的函数

    exit (没有下划线)

    清理并终止进程。

    一旦进程以exit 及其变体或信号终止,那么它会停止执行,但是不会完全消失,直到它的退出状态已经被报告给了它的父进程。一个还没有报告状态的终止进程叫做僵尸

    2011年1月17日

    第9章 信号和定时器

    前面看的都记在笔记本上了,中间也隔了好几天没看。。。

    信号屏蔽是针对每个线程的,但针对信号的动作是全进程范围的,尽管可能存在多个线程。

    9.1.4中断系统调用

         对不能被忽视的信号进行传递可能会引起系统调用的中断。如果动作是重新捕获信号并且信号处理程序也返回了,那么中断的系统调用通常不会被重新启动。相反,它通常会返回-1并将errno置为EINTR。

            要遵循的简单规则是:绝对不要从信号处理程序返回,除非已经对信号发生的上下文进行了仔细的控制。如果不想这样,即要使系统调用可以在中断后重新继续运行,可以在调用sigaction时设置SA_RESTART标志。

            大多数的阻塞系统调用都可以被中断,但并不是所有的,如pthread_mutex_lock就不可以被中断。

            可以调用sigfillset,sigaddset, sigdelset, sigismember, pthread_sigmask等屏蔽信号。

             信号处理程序运行时,不可重入。机制是系统会把调用的信号自动地加入到信号屏蔽中,当信号处理程序完成时,删除该信号的屏蔽。也就是我之前担心的定时器处理程序会不会在规定时间内没处理完时,会不会重入这个已经得到解决。

            信号传递给线程的方式:两种。一是先传递给进程,然后用随机选择的方式传递给一个未被阻塞的线程;另一种是传递给指定的线程。

    总结动作及其对线程的影响:

    。信号的动作是基于整个进程范围的,可以是捕获、忽略、终止、停止或继续

    。信号屏蔽是基于每个线程的

    。可以明确设置sigaction来捕获和忽略信号;如果是SIG_DFL,就可以捕获、忽略、终止、停止或继续。但不能具体选择是上述4个中的哪一个

    。忽略、终止、停止或继续总是应用到整个进程

    。被捕获的信号只能在一个线程中运行一个信号处理程序。如果是信号传递给进程,而不是指定某个线程,则信号会被随机传送到任一个未被阻塞的线程                      

    9.1.9人工产生信号

    kill 为进程产生信号

    pthread_kill 为线程产生信号 , 小心终止、停止和继续信号总是影响到整个进程

    abort       产生SIGABRT信号

    raise 为线程产生信号

    子进程或新建线程对信号的影响

    1)信号动作:执行fork之后,子进程将继承全部的信号动作。

    执行exec,SIG_DFL、SIG_IGN保持原样,已捕获的信号被设置为SIG_DFL,ISG_CHLD根据情况被设置为SIG_DFL或SIG_IGN

    执行phtread_create无影响,因为信号动作是整个进程范围内的

    2)信号屏蔽:fork 从父进程继承,exec也为父进程原样,pthread_create之后,从父线程复制到新线程

    3)挂起信号:执行fork,清除挂起信号

    执行 exec  , 和父进程相同

    phtread_create,清除挂起信号

    9.7时钟和定时器

    这节的东西才是我真正想要的,要不另开个文章来写这个了。

    不过来个概要吧:

    alarm系统调用   秒级的

    sleep 也是秒级的

    usleep 微秒级的睡眠

    nanosleep 纳秒级的睡眠

    基本间隔定时器       三个独立的间隔定时器可以使用 ITIMER_REAL(实时减1)、ITIMER_VIRTUAL(进程虚拟时间减1)、ITIMER_PROF(进程虚拟时间减1并且代表该进程运行的系统时间减1)

    getitimer, setitimer

    实时时钟

    clock_gettime  clock_getres得到时钟精度 clock_settime设置时钟 clock_nanosleep挂起几纳秒或等待某个信号

    高级间隔定时器

    这个应该能符合我的要求了吧。调用它可以为每个进程设置几个都基于同一时钟的间隔定时器

    timer_create

    timer_delete

    timer_gettime得到每个进程定时器的值

    timer_settime设置每个进程定时器的值

    timer_getoverrun 得到每个进程定时器消耗的时间

    这本书应该就写这么多了吧,到时如果回头再看,有兴趣也会写上这里。


    最新回复(0)