即使pthead_cond_wait()和pthread_cond_timewait()没有错误返回,等待的条件也可能是假的:即使pthread_cond_timewait()返回了超时错误,关联的条件也可能是真的:因为超时和条件改变之间有时间窗口: 在有些实现中,特别是多处理器环境,信号唤醒可能会同时唤醒多个处理器上的多个线程: 通常,不管pthread_cond_wait()返回什么,都要对条件进行重新判断,以确定下一步动作,或者继续执行,或者继续等待: 因此,推荐使用while循环来对等待…
在Stevens的<Unix 环境高级编程>中第11章线程关于pthread_cond_wait的介绍中有一个生产者-消费者的例子P311,在进入pthread_cond_wait前使用while进行条件判断,而没有直接使用if,耐人费解! 代码如下: #include <pthread.h> struct msg { struct msg *m_next; /* value...*/ }; struct msg* workq; pthread_cond_t qready = PT…
在前面学习讲完while循环之后,现在终于要将for循环这个坑填上了.之所以拖到现在是因为for循环对前面讲过的序列.字典.集合都是有效的,讲完前面的内容再来讲for循环会更加容易上手. 首先,for循环和while循环一样,都是在满足一定条件的时候对其内层的代码进行循环执行.不同的是,while循环判断的是条件,而for判断的是迭代对象.   Python 中的 for 接受可迭代对象(例如序列或迭代器)作为其参数,每次迭代其中一个元素. 我们先来看for循环的代码: a = (1, 2, 3…
umask函数设置当前进程的权限为屏蔽字:系统会有一个默认的屏蔽字,为了确保创建文件具有的权限位成功被设置,需要使用umask将屏蔽字置0: 系统屏蔽字用shell查看,比如得到如下结果,其为八进制表示形式,以0开头:这个屏蔽字表示屏蔽掉了组的写和其他的写权限: 下面的例子很好的说明了umask的使用,首先使用umask(0)将屏蔽字置0,此时新建foo文件,可见其具有设置的全部读写权限:而后用umask屏蔽掉组和其他的读写位,新建bar,可见bar之具有用户读写权限: 另外需要注意的是,进程设…
下图为调用dup之后的文件指针状态,包含如下信息: 1. dup选择了一个最小的未使用的描述符3: 2. dup(1)之后,描述符1和描述符3指向同一个文件表项: 3. dup(1)的返回值即为复制得到的描述符3: 4. 补充dup2,dup2可以指定复制的目标描述符,如果该描述符与被复制的描述符相同,会直接返回该描述符:如果不同,则会先关闭描述符,然后进行复制:注意,dup2的关闭和复制操作是原子的: 5. 补充open,进程每一次open调用都会打开一个新的文件表项,一个新的描述符指向这个文…
在main中创建线程,我们称main线程为主线程,新建线程为子线程(其实没有什么主线程和子线程的父子概念,它们是平行的,为了好理解这样称呼),如果子线程内部执行相对比较耗时的操作,主线程执行的快,而且没有等待子线程执行完毕,此时主线程退出,进程被销毁,就会导致子线程无法执行完毕: 可以采用如下方式确保子线程执行完毕: 1. 主线程中采用pthread_join阻塞等待子线程结束,并回收资源: man手册对于该函数的描述: The pthread_join() function waits for…
在信号产生和传递之间有一段时间间隔,称为信号是未决的: 进程可以设置阻塞信号传递:如果进程产生了一个阻塞的信号,并且对该信号的动作是系统默认或者捕捉该信号,则该进程保持此信号为未决状态,直到该进程对此信号接触阻塞,或者将对该信号的动作改为忽略:内核在传递一个原来被阻塞的信号给进程时(而不是产生该信号时),才决定对它的处理方式:这样就意味着进程在信号传递给它之前仍然可以改变对该信号的动作:进程调用sigpending函数来判断哪些信号是设置为阻塞并处于未决状态的: 如果进程在解除对某个信号的阻塞之…
SIGCHLD信号是当子进程终止时向父进程发送的信号:它的语义如下: 如果进程明确的将该信号设置为SIG_IGN,则调用进程不会产生僵尸进程:这种情况下,wait是等不到给子进程收尸的,所以wait阻塞到所有子进程终止后,返回-1,并且将errno设置为ECHILD: 如果进程没有明确的设置捕获该信号,那么将会是默认处理SIG_DFL(忽略),这种情况下,如果不使用wait函数,会产生僵尸进程: 如果进程明确的设置捕获该信号,则内核立即检查是否子进程准备好被等待,如果是,则调用SIGCHLD处理…
重入时间点 进程捕捉到信号并对其进行处理时,进程正在执行的正常指令序列就会被信号处理程序临时中断,它首先执行该信号粗合理程序中的指令:如果从信号处理程序返回,则继续执行捕捉到信号时进程正在执行的正常指令序列: ps:如果了解驱动,上面这段信号打断流程与中断打断进程上下文很类似: 不可重入函数 对于有些函数,是不可重入的,如果信号处理程序打断了这些函数的执行,同时信号粗合理程序中也调用这个函数,就会发生错误:这些不可重入的函数,有如下特点: 1. 使用了静态的数据结构: 2. 调用了malloc或…
如果进程在执行一个低速系统调用而阻塞期间捕获到一个信号,则该系统调用就会被中断而不再继续执行:该系统调用返回出错,其errno设置为EINTR: 系统将系统调用分成两类:低速系统调用和其他系统调用:低速系统调用是可能会使进程永远阻塞的一类系统调用,包括: 1. 如果某类型文件(如读管道,终端设备,网络设备等)的数据不存在,则读操作可能会使调用者永远阻塞: 2. 如果数据不能被相同类型的文件立即接受,则写操作可能会使调用者永远阻塞: 3. 在某种条件发生之前打开某些类型文件,可能会发生阻塞(如要打…