目录
1.linux线程
1.1 基本介绍
1.2 线程信息
1.3 线程创建
1.4 线程终止
1.5 线程指定数据
1.5 线程同步
2.linux 信号与信号处理
2.1 信号介绍
2.2 信号种类
2.3 信号处理
2.4 信号发送
2.5 信号屏蔽
线程是计算机独立运行的最小单位,也可以看出线程是系统分配CPU资源的基本单位,每个线程在系统给它时间片内,取得CPU的控制权,执行线程中的代码。
相对于进程来说,线程创建消耗资源少,线程切换速度快,进程内的线程数据共享,通信效率高。
线程ID,每个线程有唯一的线程ID
寄存器,如PC计数器,堆栈指针等
堆栈
信号掩码
优先级
线程私有空间等。
#include
typedef struct
{
int detachstate; /*
/*create_thread.c example*/
#include
#include
#include
#include
int* thread_routine(void* arg);
int main(void)
{
pthread_t thid;
printf("main thread id is %u \r\n",pthread_self());
if (pthread_create(&thid,NULL,(void*)thread_routine,NULL) != 0)
{
printf("thread create failed! \r\n");
exit(1);
}
sleep(1);
exit(0);
}
int* thread_routine(void* arg);
{
pthread_t thid;
thid = pthread_self();
printf("routine thread id is %u \r\n",thid);
return NULL;
}
1> 从线程函数中,通过return返回终止;
2> 调用pthread_exit() 终止线程。
线程终止时的资源释放,如下成对出现的红函数,可以跟着线程的终止而释放资源
#include
#define pthread_cleanup_push(routine,arg) \
{ struct _pthread_cleanup_buffer buffer; \
_pthread_cleanup_push(&buffer,(routine),(arg));
#define pthread_cleanup_pop \
_pthread_cleanup_pop(&buffer,(routine));}
线程间的同步等待
#include
/*@desp,线程退出
*
*/
void pthread_exit(void* ret);
/*@desp,挂起自己,等待一个线程结束,
* 一个线程仅仅允许一个线程等待终止
*/
int pthread_join(pthread_t th,void* thread_ret);
/*@desp,设置线程是否允许被同步
*
*/
int pthread_detach(pthread_t th);
线程指定数据(thread specific data TSD),通过键值访问方式,来达到线程私有数据目的。
具体方法是,各个线程,使用公有的键来访问线程数据,而每个线程中使用该键对应的数据是不一致的,以此,达到私有数据访问的目的。
#include
/*@desp,为线程,创建键值,私有数据*/
int pthread_key_create(pthread_key_t *key,void (*destr_function)(void*));
/*@desp,设置键值对应的私有数据*/
int pthread_setspecific(pthread_key_t key,const void * ptr);
/*@desp,获取键值对应的私有数据*/
void* pthread_getspecific(pthread_key_t key);
/*@desp,删除键值*/
int pthread_key_delete(pthread_key_t key);
同步的方式,主要包含,互斥锁,条件变量,异步信号。
互斥锁
#include
/*锁的属性
* PTHREAD_MUTEX_TIMED_NP 普通锁,加锁后,形成等待队列
* PTHREAD_MUTEX_RECURSIVE_NP 嵌套锁,允许同一线程多次加锁,多次解锁;
* PTHREAD_MUTEX_ERRORCHECK_NP 检错锁,同一线程,请求同一个锁,返回EDEADLK;
* PTHREAD_MUTEX_ADAPTIVE_NP 适应锁,解锁后,重新竞争
*/
/*初始化锁*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/*或初始化锁*/
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);
/*加锁,若已被锁,则阻塞,直到释放锁*/
int pthread_mutex_lock(pthread_mutex_t *mutex);
/*或加锁,若已被锁,则立即返回busy*/
int pthread_mutex_trylock(pthread_mutex_t *mutex);
/*解锁*/
int pthread_mutex_unlock(pthread_mutex_t *mutex);
/*清除互斥锁,解锁后,才能清除成功*/
int pthread_mutex_destroy(pthread_mutex_t *mutex);
条件变量
#include
/*初始化条件变量*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
/*或初始化条件变量*/
int pthread_cond_init(pthread_cond_t 8cond,pthread_condattr_t *cond_attr);
/*等待条件变量成立,否则阻塞*/
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
/*等待条件变量成立,等待指定时间*/
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const struct timespec *abstime);
/*激活条件,激活队列中靠前那一个*/
int pthread_cond_signal(pthread_cond_t *cond);
/*激活条件,激活所有队列*/
int pthread_cond_broadcast(pthread_cond_t *cond);
/*清除条件,只有没有等待时,才能清除*/
int pthread_cond_destroy(pthread_cond_t *cond);
异步信号
#include
/*向特定线程,发送信号*/
int pthread_kill(pthread_t threadid,int signo);
/*设置信号掩码,如屏蔽或解除屏蔽等*/
int pthread_sigmask(int how,const sigset_t *newmask,sigset_t *oldmask);
/*等待异步信号*/
int sigwait(const sigset_t *set,int *sig);
信号是一种软中断,一种处理异步事件的方式,主要用来通知进程发生了事件,以及传递数据。
信号的来源:终端按键,硬件异常,kill、sigqueue发送信号,alarm/timer等发送信号等;
信号 | 说明 |
SIGHUP | 用户退出shell,该shell启动的进程收到该信号,默认为退出进程 |
SIGINT | 用于按下 CTRL+C 发出该终端启动的程序该信号,默认为终止进程 |
SIGQUIT | 用于按下 CTRL+\ 向正在运行的程序发出该信号,默认终止进程,产生core文件 |
SIGILL | CPU 检测非法指令,终止进程,产生core文件 |
SIGTRAP | 断点指令或trap指令产生,终止进程,产生core文件 |
SIGABRT | 调用abort函数产生该信号,终止进程,产生core文件 |
SIGBUS | 非法访问地址,内存地址对齐出错,终止进程,产生core文件 |
SIGFPE | 致命的算术错误,如浮点运算错误,溢出,除0等,终止进程,产生core文件 |
SIGKILL | 无条件终止进程,不可被忽略 处理和阻塞 |
SIGUSR1 | 用户定义信号 |
SIGSEGV | 进程进行了无效的内存访问,终止进程,产生core文件 |
SIGUSR2 | 用户定义信号 |
SIGPIPE | broken pipe,向一个没有读端的管道写数据 |
SIGALRM | 定时器超时,系统调用alarm设置 |
SIGTERM | 程序terminate信号,可被阻塞和处理,执行kill是产生这个信号 |
SIGCHLD | 子进程结束时,父进程收到该信号,默认忽略该信号 |
SIGCONT | 让一个暂停的进程继续执行 |
SIGSTOP | stop 进程的执行,只是让进程暂停,不可被忽略处理和阻塞 |
SIGTSTP | 停止进程的运行,可被处理和忽略, 一般CTRL+Z发出,默认为暂停进程 |
SIGTTIN | 后台进程从用户终端读数据,终端进程收到该信号,默认暂停进程 |
SIGTTOU | 后台进程从用户终端写数据,终端进程收到该信号,默认暂停进程 |
SIGURG | 套接字 socket有紧急数据时,向正在运行的进程发出该信号,默认动作为忽略 |
SIGXCPU | 进程执行时间超过分配给该进程的CPU时间,默认为终止进程 |
SIGXFSZ | 超过文件最大长度限制,终止进程,产生core文件 |
SIGVTALRM | 虚拟时钟超时,默认动作终止进程 |
SIGPROF | 同SIGVTALRM |
SIGWINCH | 窗口大小改变发出,默认忽略该信号 |
SIGIO | 异步IO事件,默认忽略 |
SIGPWR | 关机,默认终止进程 |
SIGSYS | 无效的系统调用,终止进程,产生core文件 |
SIGRTMIN~SIGRTMAX | linux 实时信号,无固定意义 |
1~31 不可靠信号 | 33~64 可靠信号,不会丢失 |
优先级 | 实时信号,值越小,优先级越高 |
#include
typedef void (*sighandler_t)(int);
struct sigaction
{
void (*sa_handler)(int); /*
#include
#include
#include
int tmp = 0;
void sigint_handler(int signo);
int main(void)
{
struct sigaction act;
act.sa_handler = sigint_handler;
act.sa_flags = SA_NOMASK;
sigaction(SIGINT,&act,NULL);
while(1);
exit(0);
}
void sigint_handler(int signo)
{
printf("recv SIGINT\n");
sleep(5);
tmp++;
printf("tmp value is %d \n",tmp);
}
执行以上程序,按CTRL+C 出现效果,按CTRL+\ 退出
#include
/*使调用进程挂起,直到捕获到信号*/
int pause(void);
kill 函数发送
int kill(pid_t pid,int sig);
pid>0 发送给指定pid信号
pid=0,发送给进程组
pid=-1 广播给除init和自身的所有进程
pid < -1,进程组-pid的所有进程
raise函数发送
int raise(ing sig);
sigqueue函数发送
int sigqueue(pid_t pid,int sig,const union sigval var);
支持带参数的发送信号
alarm函数发送
unsigned int alarm(unsigned int seconds);
按设定的时间发送SIGALRM信号
abort函数发送
void abort(void);
发送SIGABRT信号
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);
how,主要包含如下设置
SIG_BLOCK,设置为信号集并集 set| oldset
SIG_SETMASK,设置为set
int sigpending(sigset_t *set);
获取当点pending的信号集
int sigsuspend(const sigset_t *mask)
将信号屏蔽码设置为mask,和pause一样,等待信号的发生并执行信号处理函数。