ps axj
命令查看系统中的进程。参数a
表示不仅列当前用户的进程,也列出所有其他用户的进程,参数x
表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j
表示列出与作业控制相关的信息;
凡是TPGID
一栏写着-1的都是没有控制终端的进程,也就是守护进程;
在COMMAND
一列用[]
括起来的名字表示内核线程,这些线程在内核里创建,没有用户空间代码,因此没有程序文件名和命令行,通常采用以k
开头的名字,表示Kernel;
udevd
负责维护/dev
目录下的设备文件,acpid
负责电源管理,syslogd
负责维护/var/log
下的日志文件,可以看出,守护进程通常采用以d
结尾的名字,表示Daemon;
创建守护进程最关键的一步是调用setsid
函数创建一个新的Session,并成为Session Leader;
创建守护进程;
线程库函数是由POSIX标准定义的,称为POSIX thread或者pthread。在Linux上线程函数位于libpthread
共享库中,因此在编译时要加上-lpthread
选项;
终止线程
如果需要只终止某个线程而不终止整个进程,可以有三种方法:
-
从线程函数
return
。这种方法对主线程不适用,从main
函数return
相当于调用exit
。 -
一个线程可以调用
pthread_cancel
终止同一进程中的另一个线程。 -
线程可以调用
pthread_exit
终止自己。
线程可以调用pthread_join
得到start_routine
的返回值;
调用该函数的线程将挂起等待,直到id为thread
的线程终止。thread
线程以不同的方法终止,通过pthread_join
得到的终止状态是不同的,总结如下:
-
如果
thread
线程通过return
返回,value_ptr
所指向的单元里存放的是thread
线程函数的返回值。 -
如果
thread
线程被别的线程调用pthread_cancel
异常终止掉,value_ptr
所指向的单元里存放的是常数PTHREAD_CANCELED
。 -
如果
thread
线程是自己调用pthread_exit
终止的,value_ptr
所指向的单元存放的是传给pthread_exit
的参数。
如果对thread
线程的终止状态不感兴趣,可以传NULL
给value_ptr
参数。
一般情况下,线程终止后,其终止状态一直保留到其它线程调用pthread_join
获取它的状态为止。但是线程也可以被置为detach状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join
,这样的调用将返回EINVAL
。对一个尚未detach的线程调用pthread_join
或pthread_detach
都可以把该线程置为detach状态,也就是说,不能对同一线程调用两次pthread_join
,或者如果已经对一个线程调用了pthread_detach
就不能再调用pthread_join
了。
#include <pthread.h> int pthread_detach(pthread_t tid);
对于多线程的程序,访问冲突的问题是很普遍的,解决的办法是引入互斥锁(Mutex,Mutual Exclusive Lock),获得锁的线程可以完成“读-修改-写”的操作,然后释放锁给其它线程,没有获得锁的线程只能等待而不能访问共享数据,这样“读-修改-写”三步操作组成一个原子操作,要么都执行,要么都不执行,不会执行到中间被打断,也不会在其它处理器上并行做这个操作。
Mutex用pthread_mutex_t
类型的变量表示,可以这样初始化和销毁:
#include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex); int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Mutex的加锁和解锁操作可以用下列函数:
#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);
一个线程可以调用pthread_mutex_lock获得Mutex,如果这时另一个线程已经调用pthread_mutex_lock获得了该 Mutex,则当前线程需要挂起等待,直到另一个线程调用pthread_mutex_unlock释放Mutex,当前线程被唤醒,才能获得该 Mutex并继续执行。
如果一个线程既想获得锁,又不想挂起等待,可以调用pthread_mutex_trylock,如果Mutex已经被另一个线程获得,这个函数会失败返回EBUSY,而不会使线程挂起等待。
想尽方法仅仅执行一条指令,保证操作原子性;
用pthread_mutex_trylock调用代替pthread_mutex_lock调用,以免死锁;