Linux进程与线程
1、进程与线程的概念:略
2、Linux进程结构
Linux使用一个称为进程控制块的数据结构task_struct来代表一个进程(注:task_struct在include\Linux\sched.h文件中定义),主要成员包括:
1.进程状态(volatile long state):进程有可运行状态(0),不可运行状态(-1),暂停状态(>0)
2.运行标志(unsigned long flags):描述进程管理信息或过度状态,可取值:a.#define PF_STARTING 0x00000002 /*进程被创建*/ b.#define PF_EXITING 0x00000004 /*进程开始关闭*/ c.PF_FORKNOEXEC:刚创建还没开始运行 d.PF_SUPERPRIV:超级用户特权 e.PF_DUMPCORE:标志进程是否清空core文件 f.PF_SIGNALED:进程被信号终止 g.PF_MEMALLOC:进程正在分配主寸 h.PF_VFORK:用vfork()创建,退出前在唤醒父进程 i.PF_USEDFPU:该进程使用FPU,此标志只在SMP时使用
3.跟踪标志(unsigned long ptrace):包括以下几个状态:a.PF_PTRACED:进程跟踪标志; b.PF_TRACESYS:正在跟踪函数; c.PF_DTRACE:进程延期跟踪标志
4.进程优先级(int prio,static_prio,normal_prio/*动态,静态和正常优先级*/;unsigned long rt_priority:实时进程优先级)
5.进程进入就绪态原因
6.运行时间片剩余大小
总结:写了这么多,只是想告诉你,进程的实现是十分复杂的!!!
3、进程标识符信息: #include<sys/types.h>
#include<unistd.h>
uid_t getpid() /* 获取进程id */
uid_t getppid() /* 获取父进程id */
pid_t getpgrp() /* 获取进程组id */
pid_t getpgid(pid_t pid) /* 获得指定pid进程所属组的id */
uid_t getuid() /* 获得进程所有者id */
uid_t geteuid() /* 获得进程有效所有者id */
git_t getegid() /* 获取进程的有效组id */
代码getpidtest.c显示获取进程id方法
4、Linux进程状态
task_struct中的state成员表示,linux定义了7种进程状态:TASK_RUNNING(0,正在运行的进程或者等待被调度的进程)、TASK_INTERRUPTIBLE(1)、TASK_UNINTERRUPTIBLE(2)、TASK_STOPPED(4)、TASK_TRACED(8)、TASK_ZOMBIE(16)、TASK_DEAD(32)
关于这些进程状态的不同以及如何转化,由于比较复杂,就不码了。
5、进程控制
5.1创建进程
Linux进程都用函数fork(),vfork(),clone()创建新进程:pid_t fork(), pid_t vfork(), int clone(int (*fn)(void* arg), void* stack, int flag, void* args),三个进程都调用统一个内核函数:do_fork(unsigned long clone_flag, unsigned long usp, state pt_regs),其中clone_flag包括CLONE_VM(进程空间)、CLONE_FS(文件系统信息)、CLONE_FILES(打开文件)、CLONE_SIGHAND(信号处理函数)、CLONE_PID(进程标识符)、CLONE_VFORK(父进程在子进程释放空间时被唤醒)等标志,其中任意一位置一,则表明创建的子进程和父进程共享该位对应资源。
do_fork()的执行过程大致为:1、调用alloc_pidmap()为子进程分配pid;2、调用copy_process()它将完成创建的大部分工作。。。
vfork()函数创建的子进程与父进程共享地址空间,即子进程完全运行在父进程的地址空间上,用vfork()创建子进程后,父进程会被阻塞,直至子进程调用exec()或exit()。
int clone(int (*fn)(void* arg), void* stack, int flag, void* args)是创建Linux线程的函数,fn是线程执行的函数,stack是线程使用的内核栈,flags由用户指定,可以是CLONE_VM、CLONE_FS、CLONE_FILES等的组合
5.2运行新进程:通过exec()类函数实现。
5.3进程等待
与vfork()不同,fork()创建的子进程与父进程的执行顺序无法控制,如果项控制,必须由父进程使用函数wait()或waitpid()。
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int* status)
pid_t waitpid(pid_t pid, int *status, int options)
5.4进程终止:使进程自动退出系统的函数是exit()或者_exit()
6、多线程编程
6.1 线程的创建:
#include<pthread.h>
int clone(int (*fn)(void* arg), void *stack, int flags, void* arg)
int pthread_create(pthread_t *tidp, const pthread_attr_t* attr, void* (*start_rnt6)(void), void *arg);(好复杂的原型)
6.2 线程等待
父进程可以使用pthread_join()等候子进程终止,其函数原型如下:
#include<pthread.h> int pthread_join(pthread_t thread, void** status);
6.3 线程同步的函数:线程信号量同步原语:sem_init()、sem_wait()、sem_post()、sem_destroy() 线程互斥量同步原语:pthread_mutex_init,pthread_mutex_lock,pthread_mutex_unlock,pthread_mutex_destroy
6.4 线程终止:void pthread_exit()
6.5 线程标识:可通过pthread_self()获取,其函数原型为:pthread_t pthread_self()