sleep(指linux应用程序通过libc调用的---》nanosleep())将置task状态为interruptable
wait queue将根据用户选择置task状态为interruptable or uninterruptable
内核信号量将置task状态为uninterruptable
如果进程的状态为interruptable(当没有信号pending的时候) or uninterruptable, 在切换时,将从run queue的active array中取下。
linux内核也用sleep_on()(uninterruptable)和interruptable_sleepon()(inerruptable) for 编写内核函数.
今天研究了一下linux pthread。
thread被创建时的初始参数是derefer, cancel enable的, 但是只有线程运行了并且遇到cancel点的时候才会退出,不会在线程还没有运行一行代码时就退出。 退出时调用linux的exit(), exit()会把进程状态设为PF_DEAD, 这样在schedule()的时候会把它从运行队列里面取下。
有这么几个取消点:
pthread_join(3 )
pthread_cond_wait(3 )
pthread_cond_timedwait(3 )
pthread_testcancel(3 )
sem_wait(3 )
sigwait(3 )
还有一些引起阻塞的系统调用也是, 如printf, sleep等
下面是一段测试代码:
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
void * test_t1(void * xx) {
int i;
for(i = 0; i<100; i++) {
printf("t1 id = %u, i = %d/n", pthread_self(), i);
}
return NULL;
}
void * test_t2(void * xx) {
int i;
for(i = 0; i<100; i++) {
printf("tttttt2 id = %u, i = %d/n", pthread_self(), i);
//pthread_testcancel();
}
return NULL;
}
int main(){
int i;
pthread_t tid1;
pthread_t tid2;
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid2, NULL, test_t2, NULL);
pthread_cancel(tid2);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
pthread_create(&tid1, NULL, test_t1, NULL);
printf("main thread end/n");
sleep(100);
printf("main thread end2/n");
pthread_join(tid1, NULL);
printf("main thread end3/n");
return 0;
}
在//pthread_testcancel();被mask后, test2线程在多次循环后结束(没有循环100次的原因是后面的主线程延时较短)。 而如果去掉mask, 只运行几次, 比如1次, 2次(看pthread_cancel何时起作用), 经多次测试, 没有发现一次都没有执行 的情况。这里printf()本身似乎也是可以作为线程取消点的。