守护进程:
- 进程组:也被称为作业,代表一个或多个进程的集合,每个进程都属于一个进程组,用来可以简化对进程的管理,用进程组id就可以实现对多个进程的管理,当父进程创建子进程的时候默认子进程与父进程属于同一组。进程组id就是该进程组的第一个进程的id,也就是组长id,第一个进程就是组长。可以使用kill -SIGKILL -进程组id(负的)来杀死整个进程组,组长进程可以创建一个进程组,创建该进程组中的进程,然后终止,只要进程组中有一个进程存在,进程组就存在,与父进程是否存在无关。一个进程组结束的标志就是该进程中的最后一个进程离开(终止或者转移到另一个进程组)。
- 会话:会话是一个或多个进程组的集合,也就是比进程组更高一级。(创建会话的注意事项)
- 创建会话就要调用一个进程,并且调用进程不能是进程组的组长,如果是进程组的组长的话将会出错返回
- 调用的这个进程将会便变成新会话首进程(会长),该进程也将会变成一个新进程组的组长进程,新的会话将会丢弃原有会话和原有会话的控制终端,并且该会话没有控制终端
3.4.5.7都不是必须的,调试的时候5最好别关
举例:创建一个守护进程每分钟在家目录下创建一个文件(但是我不知道是不是代码有问题,创建的文件都是红色高亮)
线程概念 :
轻量级进程,一个进程内部可以有多个线程,默认情况下一个进程只有一个线程
进程内部有线程,一个进程内部最少一个线程,若是创建线程那么线程共享的是进程虚拟内存除栈外的其他所有东西,每个线程执行一个函数 栈上存放的是不同的函数和变量,所以不能共享(我感觉就是线程是进程的具体化,比如说一个线程执行一个任务,然后其实是进程内部的线程执行任务,线程是苦力)
- 线程:最小的执行单位
- 进程:最小的资源分配单位
- 每个线程都有自己的pcb
假如说你的电脑只有一个cpu,刚好你的一个进程分到了cpu资源,这个进程内部若是只含有一个线程的话,那么就是这一个线程进行工作,要是含有多个线程的话,还是只有一个线程进行工作,因为只有一个cpu资源,要是电脑有四个cpu然后恰好同一个进程分到四个cpu资源那么这个进程内部的线程就可以有多个获得cpu资源运行速度更快
lwp线程编号,看上面第一点的英文多缩写
线程共享资源:
⦁ 1.文件描述符
⦁ 2.每种信号的处理方式
⦁ 3.当前工目录
⦁ 4.用户组ID和组ID
⦁ 5.内存地址空间(除栈之外)
线程非共享资源:
⦁ 1.线程id
⦁ 2.处理器现场哈栈指针(内核栈)
⦁ 3.error变量
⦁ 4.独立色栈空间(用户空间栈)
⦁ 5.信号屏蔽字
⦁ 6.调度优先级
线程的优缺点:
优点:
⦁ 提高并发性,充分利用cpu
⦁ 占用资源小
⦁ 通信方便
缺点:
⦁ 编写调试困难
⦁ 线程属于库函数,库函数不稳定
⦁ 对信号支持不好
compile and link with -pthread 进行编译的时候加上-pthread因为线程属于库函数
thread:创建好的线程,传出参数
attr:代表线程的属性
第三个参数 函数指针,void* func (void*)
arg:线程执行函数的参数
成功返回0 ,失败返回erron
编译的时候需要加上pthread库
可以看出两个线程的pid相同
现在再介绍一个函数用来获取线程tid 的函数(man pthread_self)
pthread_t pthread_self(void);
返回的类型是pthread_t(无符号长整型)
运行结果可以看出,在同一个进程中的线程tid不同
进程是独立的。创建它的线程关闭了,进程还在。相反,线程隶属于进程,创建线程的进程退出了,线程也就退出了。
这个也就说明了为什么上面要在主函数中让主函数睡一秒钟,因为如果主函数不睡的话创建的线程还没有来得及运行函数,主函数就退出了,线程也就没来得及执行函数就退出了
介绍一个函数,线程退出函数,对上面的sleep进行优化:man pthread_exit
void pthread_exit(void *retval);
retval:传入参数返回一个值用来判断线程
在线程执行的这个函数里面有三种退出方式return pthread_exit exit
前两种都只是使当前线程退出(但是在主控线程里面的return就是退出整个进程,所以在主控线程中只能使用第二种退出退出线程),第三种直接是使当前进程退出,也就是说这个线程退出后,整个进程都没得玩,即使进程还有任务没有执行完毕,那么整个程序也将退出
线程回收函数:(阻塞等待)举例在后面
int pthread_join(pthread_t thread, void **retval);
thread:创建线程的时候传出的第一个参数
retval:传出参数,传出线程的退出信息 ,不需要填NULL
返回值:成功返回0,失败返回错误信息的值
运行结果是,创建的线程睡了5秒钟后再运行退出后,父进程才打印,说明pthread_join是阻塞等待
取消函数:(杀死线程)
int pthread_cancel(pthread_t thread);
参数创建线程的时候的传出参数
返回值:成功返回0,失败返回-1
被杀死的线程线程退出状态为-1
线程分离:
int pthread_detach(pthread_t thread);
参数是创建线程时候的传出参数
执行线程分离之后,线程再也不需要pthread_join来回收,系统可以自动回收
线程共享全局变量
int pthread_equal(pthread_t t1, pthread_t t2);判断两个线程tid是否相等
线程id在进程内部可以唯一标识,但是在整个系统中不唯一和线程不一样
创建多个进程并以此回收:
查看线程库版本:
getconf GNU_LIBPTHREAD_VERSION
之前说的线程库不稳定就是因为版本不同,稍微有差别
创建多少个线程合适?
cpu核数*2+2