
进程1. 获取进程信息---进程时间 times() / clock()2. 进程 的概念2.1 进程号---getpid() / getppid() / getpgid() / getpgrp() / setpgid() / setpgrp() / getsid() / setsid()2.2 进程的 环境变量---getenv() / putenv() / setenv() / unsetenv() / clearenv()2.3 进程的内存布局2.4 进程的操作---fork() / vfork() / wait() / waitpid() / waitid() / execve() / execl() / execlp() / execle() / execv() / execvp() / execvpe() / system()2.5 孤儿进程 、 僵尸进程 和 守护进程2.6 进程状态与进程关系3. 进程间通信3.1 信号3.1.1 信号的操作 signal() / sigaction() / kill() / killpg() / raise() / alarm() / pause() / sigpending() / sigqueue() / abort()3.1.2 信号掩码(阻塞信号传递)---sigprocmask()3.1.3 阻塞等待信号---sigsuspend()3.2 管道3.2.1 管道的操作---pipe() / mkfifo()3.3 消息队列3.3.1 消息队列的操作---msgget() / msgsnd() / msgrcv() / msgctl()3.4 信号量3.4.1 信号量的操作---semget() / semop() / semctl() / sem_open() / sem_wait() / sem_trywait() / sem_post() / sem_close() / sem_unlink() / sem_init() / sem_destroy()3.5 共享内存3.5.1 共享内存的操作---shmget() / shmat() / shmdt() / shmctl()4. POSIX 互斥锁4.1 互斥锁 的操作---pthread_mutex_init() / pthread_mutex_lock() / pthread_mutex_trylock() / pthread_mutex_unlock() / pthread_mutex_destroy()1. 获取进程信息—进程时间times() / clock()进程时间用户CPU时间系统CPU时间#includesys/times.h#includetime.hclock_ttimes(structtms*buf);// 系统调用用于获取当前进程时间clock_tclock(void);// C库用于获取当前进程时间不能获取到单独的用户CPU时间和系统CPU时间2.进程的概念2.1进程号—getpid() / getppid() / getpgid() / getpgrp() / setpgid() / setpgrp() / getsid() / setsid()#includesys/types.h#includeunistd.hpid_tgetpid(void);//系统调用用来获取本进程的进程号pid_tgetppid(void);//系统调用用来获取父进程的进程号pid_tgetpgid(pid_tpid);//系统调用用来获取进程对应的进程组IDpid_tgetpgrp(void);//系统调用用来获取进程对应的进程组IDintsetpgid(pid_tpid,pid_tpgid);//系统调用用来加入一个现有的进程组或创建一个新的进程组intsetpgrp(void);//系统调用用来加入一个现有的进程组或创建一个新的进程组pid_tgetsid(pid_tpid);//系统调用用来获取进程的会话IDpid_tsetsid(void);//系统调用用来创建一个会话2.2 进程的环境变量—getenv() / putenv() / setenv() / unsetenv() / clearenv()#includestdlib.hchar*getenv(constchar*name);//C库用于获取指定环境变量不应该去修改其返回的字符串修改该字符串意味着修改了环境变量对应的值intputenv(char*string);//C库用于向进程的环境变量数组中添加一个新的环境变量或者修改一个已经存在的环境变量对应的值intsetenv(constchar*name,constchar*value,intoverwrite);//C库用于向进程的环境变量列表中添加一个新的环境变量或者修改一个已经存在的环境变量对应的值intunsetenv(constchar*name);// C库用于从环境变量表(environ)中移除参数name标识的环境变量intclearenv(void);// C库用于清除环境变量表中的所有变量然后再进行重建也可以通过将全局变量environ赋值为 NULL 来清空所有变量2.3 进程的内存布局2.4 进程的操作—fork() / vfork() / wait() / waitpid() / waitid() / execve() / execl() / execlp() / execle() / execv() / execvp() / execvpe() / system()#includesys/types.h#includesys/wait.h#includeunistd.h#includestdlib.hpid_tfork(void);//系统调用用于创建一个新的进程子进程拷贝了父进程的数据段、堆、栈以及继承了父进程打开的文件描述符父进程与子进程并不共享存储空间但是共享代码段每个进程均可修改各自的栈数据以及堆段中的变量而并不影响另一个进程pid_tvfork(void);//系统调用与 fork()函数在功能上是相同的但其效率要高于fork()函数为子进程立即执行 exec()新的程序而专门设计的pid_twait(int*status);//系统调用用于等待进程的任一子进程终止同时获取子进程的终止状态信息最后回收子进程的一些资源pid_twaitpid(pid_tpid,int*status,intoptions);//系统调用功能同 wait() 一样只是突破了 wait() 函数的限制WIFEXITED(status)//如果子进程正常终止则返回trueWEXITSTATUS(status)//返回子进程退出状态是一个数值其实就是子进程调用_exit()或exit()时指定的退出状态WIFSIGNALED(status)//如果子进程被信号终止则返回trueWTERMSIG(status)//返回导致子进程终止的信号编号WCOREDUMP(status)//如果子进程终止时产生了核心转储文件则返回trueintwaitid(idtype_tidtype,id_tid,siginfo_t*infop,intoptions);//系统调用与 waitpid() 类似不过waitid()提供了更多的扩展功能intexecve(constchar*filename,char*constargv[],char*constenvp[]);//系统调用将一个外部的可执行文件加载到进程的内存空间运行使用新的程序替换旧的程序而进程的栈、数据、以及堆数据会被新程序的相应部件所替换然后从新程序的main()函数开始执行intexecl(constchar*path,constchar*arg,...);// C库基于系统调用execve()而实现的intexeclp(constchar*file,constchar*arg,...);// C库基于系统调用execve()而实现的intexecle(constchar*path,constchar*arg,...);// C库基于系统调用execve()而实现的intexecv(constchar*path,char*constargv[]);// C库基于系统调用execve()而实现的intexecvp(constchar*file,char*constargv[]);// C库基于系统调用execve()而实现的intexecvpe(constchar*file,char*constargv[],char*constenvp[]);// C库基于系统调用execve()而实现的intsystem(constchar*command);// C库可以在程序当中执行任意shell命令system()函数其内部的是通过调用fork()、execl()以及 waitpid()这三个函数来实现它的功能首先system()会调用fork()创建一个子进程来运行shell可以把这个子进程成为shell进程并通过shell执行参数command所指定的命令子进程调用_exit退出父进程调用exit退出否则会导致对父进程 stdio 缓冲区的刷新和关闭exit()函数会执行的动作如下:如果程序中注册了进程终止处理函数那么会调用终止处理函数刷新stdio流缓冲区执行_exit()系统调用2.5孤儿进程、僵尸进程和守护进程2.6 进程状态与进程关系Linux 系统下进程通常存在6种不同的状态就绪态、运行态、僵尸态、可中断睡眠状态浅度睡眠、不可中断睡眠状态深度睡眠以及暂停态进程间存在着多种不同的关系无关系相互独立、父子进程关系、进程组以及会话3.进程间通信进程间通信的机制有信号、管道、消息队列、信号量、共享内存、套接字Socket3.1 信号3.1.1 信号的操作 signal() / sigaction() / kill() / killpg() / raise() / alarm() / pause() / sigpending() / sigqueue() / abort()#includesignal.h#includesys/types.h#includeunistd.h#includestdlib.hsig_tsignal(intsignum,sig_thandler);// 系统调用用于将信号的处理方式设置为捕获信号、忽略信号以及系统默认操作intsigaction(intsignum,conststructsigaction*act,structsigaction*oldact);// 系统调用允许单独获取信号的处理函数而不是设置并且还可以设置各种属性对调用信号处理函数时的行为施以更加精准的控制intkill(pid_tpid,intsig);//系统调用用于将信号发送给指定的进程或进程组中的每一个进程intkillpg(intpgrp,intsig);//系统调用用于向整个进程组发送信号intraise(intsig);//C库用于向自身发送信号intsigqueue(pid_tpid,intsig,constunionsigval value);//系统调用用于向另一个进程发送实时信号unsignedintalarm(unsignedintseconds);//系统调用用于设置一个定时器闹钟当定时器定时时间到时内核会向进程发送 SIGALRM 信号intpause(void);//系统调用用于进程暂停运行、进入休眠状态直到进程捕获到一个信号为止只有执行了信号处理函数并从其返回时pause()才返回intsigpending(sigset_t*set);//系统调用用于查询进程中处于等待状态的信号voidabort(void);//C库通常产生SIGABRT信号来终止调用该函数的进程SIGABRT信号的系统默认操作是终止进程运行、并生成核心转储文件3.1.2 信号掩码(阻塞信号传递)—sigprocmask()#includesignal.hintsigprocmask(inthow,constsigset_t*set,sigset_t*oldset);//系统调用用于向信号掩码中添加 / 移除信号3.1.3 阻塞等待信号—sigsuspend()#includesignal.hintsigsuspend(constsigset_t*mask);//系统调用用于将进程的信号掩码设置为参数mask所指向的信号集然后挂起进程直到捕获到信号被唤醒如果捕获的信号是mask信号集中的成员将不会唤醒、继续挂起、并从信号处理函数返回一旦从信号处理函数返回sigsuspend()会将进程的信号掩码恢复成调用前的值。3.2管道管道分两种类型匿名管道普通管道pipe、流管道s_pipe、有名管道3.2.1 管道的操作—pipe() / mkfifo()#includefcntl.h#includeunistd.hintpipe(intpipefd[2]);//系统调用用于创建一个匿名管道数组pipefd是用于返回两个引用管道末端的文件描述符pipefd[0]指管道的读取端pipefd[1]指向管道的写端intmkfifo(constchar*pathname,mode_tmode);//系统调用用于创建一个有名管道3.3消息队列3.3.1 消息队列的操作—msgget() / msgsnd() / msgrcv() / msgctl()#includesys/types.h#includesys/ipc.h#includesys/msg.hintmsgget(key_tkey,intmsgflg);//系统调用用于创建或获取一个消息队列对象并返回消息队列标识符intmsgsnd(intmsqid,constvoid*msgp,size_tmsgsz,intmsgflg);//系统调用用于将消息写入到消息队列俗称发送一个消息ssize_tmsgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg);//系统调用用于从标识符为 msqid 的消息队列读取消息并将消息存储到 msgp中读取后把此消息从消息队列中删除也就是俗话说的接收消息intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);//系统调用用于操作消息队列比如设置或者获取消息队列的相关属性3.4信号量信号量可分为IPC信号量、POSIX信号量无名信号量、有名信号量3.4.1 信号量的操作—semget() / semop() / semctl() / sem_open() / sem_wait() / sem_trywait() / sem_post() / sem_close() / sem_unlink() / sem_init() / sem_destroy()//IPC信号量#includesys/types.h#includesys/ipc.h#includesys/sem.hintsemget(key_tkey,intnsems,intsemflg);//系统调用用于创建或者获取一个已经创建的信号量如果成功则返回对应的信号量标识符失败则返回-1intsemop(intsemid,structsembuf*sops,size_tnsops);//系统调用用于对信号量进行 PV 操作intsemctl(intsemid,intsemnum,intcmd,...);//系统调用用于对信号量集的一系列控制操作根据操作命令cmd的不同执行不同的操作//POSIX信号量---有名信号量#includesys/types.h#includesys/ipc.h#includesys/sem.hsem_t*sem_open(constchar*name,intoflag,mode_tmode,unsignedintvalue);//系统调用用于打开/创建一个有名信号量intsem_wait(sem_t*sem);//系统调用用于等待获取信号量相当于P操作intsem_trywait(sem_t*sem);//系统调用用于等待获取信号量相当于P操作如果指定信号量的计数器为0那么直接返回 EAGAIN 错误而不是阻塞等待intsem_post(sem_t*sem);//系统调用用于释放信号量相当于V操作intsem_close(sem_t*sem);//系统调用用于关闭一个信号量这表示当前进程/线程取消对信号量的使用它的作用仅在当前进程/线程其他进程/线程依然可以使用该信号量同时当进程结束的时候无论是正常退出还是信号中断退出的进程内核都会主动调用该函数去关闭进程使用的信号量即使从此以后都没有其他进程/线程在使用这个信号量了内核也会维持这个信号量intsem_unlink(constchar*name);//系统调用用于主动删除一个信号量直接删除指定名字的信号量文件//POSIX信号量---无名信号量#includesys/types.h#includesys/ipc.h#includesys/sem.hintsem_init(sem_t*semintpsharedunsignedintvalue);//系统调用用于初始化信号量不要对已初始化的信号量再做 sem_init 操作会发生不可预知的问题intsem_destroy(sem_t*sem);//系统调用用于销毁信号量其中sem是要销毁的信号量。只有用sem_init初始化的信号量才能用sem_destroy() 函数销毁intsem_wait(sem_t*sem);//系统调用用于等待获取信号量相当于P操作intsem_trywait(sem_t*sem);//系统调用用于等待获取信号量相当于P操作如果指定信号量的计数器为0那么直接返回 EAGAIN 错误而不是阻塞等待intsem_post(sem_t*sem);//系统调用用于释放信号量相当于V操作3.5共享内存3.5.1 共享内存的操作—shmget() / shmat() / shmdt() / shmctl()#includesys/ipc.h#includesys/shm.hintshmget(key_tkey,size_tsize,intshmflg);//系统调用用于创建或获取一个共享内存对象并返回共享内存标识符void*shmat(intshmid,constvoid*shmaddr,intshmflg);//系统调用用于把共享内存区对象映射到调用进程的地址空间调用成功后返回共享内存的起始地址intshmdt(constvoid*shmaddr);//系统调用用于解除进程与共享内存之间的映射的在解除映射后该进程不能再访问这个共享内存该函数并不删除所指定的共享内存区而只是将先前用shmat()函数映射好的共享内存脱离当前进程共享内存还是存在于物理内存中intshmctl(intshmid,intcmd,structshmid_ds*buf);//系统调用用于获取或者设置共享内存的相关属性4. POSIX互斥锁线程与线程间同步信号量是更好的选择互斥锁更多的是用于保护资源的互斥4.1互斥锁的操作—pthread_mutex_init() / pthread_mutex_lock() / pthread_mutex_trylock() / pthread_mutex_unlock() / pthread_mutex_destroy()pthread_mutex_tfastmutexPTHREAD_MUTEX_INITIALIZER;// 静态初始化表示默认的互斥锁即快速互斥锁互斥锁被线程1持有时此时互斥锁处于闭锁状态当线程2尝试获取互斥锁那么线程2将会阻塞直至持有互斥锁的线程1解锁为止pthread_mutex_trecmutexPTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;// 静态初始化递归互斥锁互斥锁被线程1持有时线程2尝试获取互斥锁将无法获取成功并且阻塞等待而如果是线程1尝试再次获取互斥锁时将获取成功并且持有互斥锁的次数加1pthread_mutex_terrchkmutexPTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;// 静态初始化检错互斥锁这是快速互斥锁的非阻塞版本它会立即返回一个错误代码线程不会阻塞intpthread_mutex_init(pthread_mutex_t*mutex,constpthread_mutexattr_t*mutexattr);//动态初始化intpthread_mutex_lock(pthread_mutex_t*mutex);//获得访问临界资源的权限如果已经有其他线程锁住互斥锁那么该函数会使线程阻塞直到该互斥锁解锁为止intpthread_mutex_trylock(pthread_mutex_t*mutex);//获得访问临界资源的权限如果已经有其他线程锁住互斥锁它不会阻塞当前线程如果互斥锁已被占用它会立马返回一个 EBUSY 错误intpthread_mutex_unlock(pthread_mutex_t*mutex);//释放占用的互斥锁以便系统其他线程有机会获取互斥锁访问该资源intpthread_mutex_destroy(pthread_mutex_t*mutex);//用于销毁一个互斥锁当互斥锁不再使用时可以用它来销毁