Linux中进程和线程使用的几个函数

本文详细介绍了Linux中进程和线程的相关函数,包括获取进程ID、创建进程(fork、vfork)、进程退出(exit)、进程等待(wait、waitpid)、执行进程(execl)、进程挂起(sleep)、线程创建(pthread_create)、获取线程ID(pthread_self)、线程退出(pthread_exit)以及线程同步(pthread_join、pthread_cancel、pthread_detach)等关键函数的使用和功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.linux进程相关函数

(1)获取当前进程号

        pid_t getpid(void)

        头文件:sys/types.h、unistd.h

        该函数成功返回当前ID,该函数always successful

(2)获取父进程号

        pid_t getppid(void)

        头文件:sys/types.h、unistd.h

        always successful

(3)进程创建

       (3-1) pid_t fork(void)

        头文件:sys/types.h、unistd.h

        功能:在当前进程中创建一个进程,与父进程共享代码段,复制父进程的堆栈段和数据段,子进程复制父进程,然后执行fork()后的代码。向父进程返回创建进程的进程号,在子进程中返回0。

        返回值:fork返回给父进程所创建进程的进程号,然后返回创建成功标志值为0,失败-1或者errno

        (3-2)pid_t fork(void)

        头文件:sys/types.h、unistd.h

        功能:和fork(父子进程的执行次序不确定)类似,但vfork保证了子进程先执行,子进程退出后父进程才执行,而且在创建时不像fork分配一片新的进程空间,而是在父进程的空间里执行。

(4)进程的退出

        void exit(int value) //value为0代表正常退出,非0(一般1或-1)表示非正常退出,一般会有对应情况

        父进程:exit(0)和return(0)

        子进程:exit(0)

return和exit的区别是exit停止进程并且value表示进程退出状态,return是函数返回的标志可以返回多种数据类型

exit()(库函数;sdtlib.h)和_exit(系统调用;unistd.h):终止进程以后,_exit()缓冲区不被保存,exit()缓冲区被保存

exit函数作用:进程停止运行之前,检查文件打开情况,把文件缓冲区内容写回文件。,清除其使用的内存空间,并清除其在内核中的各种数据结构。

【知识科普】:(1)缓冲I/O,对应每一个打开的文件,在内存中都有一片缓冲区,每次读文件,连续读出若干条记录,这样在下次读文件时就可以直接从内存缓冲区读取;每次写文件写入内存缓冲区,等满足一定条件,将缓冲区内容一次性写入文件。

(2)僵尸进程:几乎放弃所有的内存空间,没有任何执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态供其他进程收集,除此之外,僵尸进程不再占有任何内存空间

(5)进程的等待函数

        pid_t wait(int *status)

        头文件:sys/type.h;sys/wait.h

        功能:挂起调用他(现在)的进程,直到子进程结束,然后才接着运行该进程

        返回值:成功返回终止的那个进程的id,失败返回-1

        参数:记录进程退出的状态(正常/异常退出)

        pid_t waitpid(pid_t pid ,int *status,int options)

        头文件:sys/type.h;sys/wait.h

        参数:pid >0:等待进程ID为pid的子进程

                        =0:等待同一进程组中的任何子进程

                        =-1:等待任一子进程,此时和wait一样

                        <-1:等待绝对值为pid的进程组的任一子进程

                    options 0:和wait一样,阻塞父进程等待子进程;WNOHANG:如果pid指定的子进程没有结束,则waitpid()函数立即返回0,而不是阻塞在这个函数上等待;如果结束了,则返回该子进程的进程号。

(6)执行进程

        int execl(const char*path,const char *arg,....)

        所属库:unistd.h

        函数功能:运行可执行文件

        返回值:成功无返回值,失败返回-1或者错误信息指针

        参数:path:可执行文件路径(如liux的命令路径,如ls的路径);arg:可执行文件(既可以是二进制文件,也可以是Linux下任何可执行脚本文件)所需要的参数

        与fork()比较,保留原有进程,执行新代码。占用原有进程的巢穴,将其代码段覆盖

        exec族函数:根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。

用处:a. 当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用任何exec 函数族让自己重生。

b. 如果一个进程想执行另一个程序,那么它就可以调用fork函数新建一个进程,然后调用任何一个exec函数使子进程重生。

(7)system(调用/bin/sh来执行参数指定的命令,file父进程为bash,即linux的sh命令解析器)

        int system(const char *file)

        头文件:stdlib.h

        功能:fork+execl,fork建立子进程,用excel函数根据参数file找到并执行可执行文件

        返回值:对于fork失败,system()函数返回-1。 如果exec执行成功,也即command顺利执行完毕,则返回command通过exit或return返回的值.如果exec执行失败,也即command没有顺利执行,比如被信号中断,或者command命令根本不存在,system()函数返回127. 如果command为NULL,则system()函数返回非0值,一般为1.

system和execl相比,system不再是当前的进程

(8)进程挂起

        unsigned int sleep(unsigned int seconds)

        头文件:#include <unistd.h>

        函数说明:sleep()会令目前的进程暂停, 直到达到参数seconds 所指定的时间, 或是被信号所中断。sleep结束后被挂起的进程不一定马上执行,还是切换到就绪态等待CPU

        返回值:若进程/线程挂起到参数所指定的时间则返回0,若有信号中断则返回剩余秒数。

        void usleep(unsigned long usec)//单位为us

        由于linux调度是毫秒级,所以usleep不太准

2.linux线程相关函数

(1)线程创建函数

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, //是一个传出参数,用于保存成功创建线程之后对应的线程id
    const pthread_attr_t *restrict attr, //线程属性,默认为NULL,如果想使用具体的属性也可以修改具体的参数
             void *(*start_rtn)(void), //指向创建线程所执行函数的入口地址,函数执行完毕,则线程结束。
                  void *restrict arg); //线程主函数执行期间所使用的参数

ret-成功返回0 失败返回错误编号。注意:由于创建线程函数是一个库函数,不是系统调用函数。所以其错误信息不能用perror()进行打印,采用strerror(错误号)可以将错误信息打印出来。其中strerror函数是包含#include<string.h>之中的一个库函数。

(2)获取线程自身ID

include <pthread.h>
pthread_t pthread_self(void);

ret-调用线程的线程ID,返回值为一个无符号长整型

说明:线程id是在一个进程中的内部标识,但不同进程中的线程id可能相同。

         进程与进程中线程的代码运行按时间先后顺序

(3)比较两个线程ID

#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);

ret-若相等则返回非0值,否则返回0值

(4)单个线程退出

#include <pthread.h>

void pthread_exit(void *rval_ptr);//rval_ptr是一个无类型指针,与传递给启动例程的单个参数类似,进程中的其他线程可以通过调用pthread_join函数访问到这个指针;

返回值:无返回值,跟进程一样,线程结束的时候无法返回到它的调用者(自身)

(5)等待线程结束函数

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);//thread:被等待的线程标识符ID;rval_ptr:一个用户定义的指针,它可以用来存储被等待线程的返回值 

ret-成功返回0 否则返回错误编号

      调用线程一直阻塞,直到指定的线程调用pthread_exit,从启动例程中返回或者被取消;如果线程(指调用的在等待的pthread)只是从调用它等待它的例程中返回,rval_ptr将包含返回码;如果线程被取消,由rval_ptr指定的内存单元就设置为PTHREAD_CANCELED.如果线程已经处于分离状态,pthread_t就会调用失败,返回EINVAL。如果对线程的返回值不感兴趣,可以吧rval_prt设置为NULL。这种情况下,调用pthread_join将等待线程终止,但不获取线程的终止状态。

        分离状态说明:在默认情况下线程是非分离状态的,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。

说明:这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回 

(6)线程取消

#include <pthread.h>
int pthread_cancel(pthread_t tid);// thread 要取消线程的标识符ID

ret-成功返回0 失败返回错误码

功能:取消某个线程的执行。调用了参数是PTHREAD_CANCELD的pthread_exit函数,但是,线程可以选择或者忽略、或者立即终止、或者继续运行至Cancelation-point(取消点:会引起阻塞的系 统调用)。函数并不等待线程终止,它仅仅是提出请求。线程接收到CANCEL信号的缺省处理(即pthread_create()创建线程的缺省状态)是继续运行至取消点才会退出。

(7)分离释放线程(由系统回收线程所占资源)

#include <pthread.h>

int pthread_detach(pthread_t thread); // thread 要释放线程的标识符ID

返回值:若是成功返回0,否则返回错误的编号 

说 明:linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态。一个线程默认的状态是joinable,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)。只有当你调用了pthread_join之后这些资源才会被释放。若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放。unjoinable属性可以在pthread_create时指定,或在线程创建后在线程中pthread_detach自己, 如:pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放。如果线程状态为joinable,需要在之后适时调用pthread_join。

(8)线程清理处理函数

#include <pthread.h>
void pthread_cleanup_push(void(*rtn)(void*), void *arg);//rtn为清理函数,arg为清理函数的参数

void pthread_cleanup_pop(int execute); //调用删除上次push的清理程序

当线程执行以下动作时调用清理函数:a. 调用pthread_exit;b. 想用取消请求;c. 用非零的execute参数调用pthread_cleanup_pop;如果execute=0则函数不被调用;
注意正常从线程返回(return)的时候,不会调用该清理函数;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值