POSIX线程库pthread

pthread_create()
函数作用:创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后就开始运行相关的线程函数。
函数原型:int pthread_create(pthread_t *tidp,const pthread_attr_t *attr, void *(*start_rtn)(void*),void *arg);
参数:

  • 第一个参数为指向线程标识符的指针。

  • 第二个参数用来设置线程属性

  • 第三个参数线程运行函数的起始地址。

  • 队后一个参数是运行函数的参数。
    返回值:

  • 线程创建成功,返回0

  • 线程创建失败,返回出错编号

返回成功时,由tidp指向的内存单元被设置为新创建线程的ID,attr参数用于指定各种不同的线程属性。
新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构体中,然后将结构体的地址作为arg的参数传入。

因为pthread并非Linux系统的默认库,二十POSIX线程库。在Linux中将其作为一个库来使用,因此加上-lpthread(或 -pthread)以显式链接该库。函数在执行错误时的错误信息将作为返回值返回,并不修改系统全局变量errno,当然也无法使用perror()来打印错误信息。


pthread_join()
函数作用:用来等待一个线程的结束,线程间同步的操作。
函数原型:int pthread_join(pthread_t thread, void **retval);
函数描述:pthread_join()函数以阻塞的方式等到thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。并且thread知道你过的线程必须是joinable。
参数:

  • thread:线程标识符,即线程ID
  • retval:用户定义的指针,用来储存被等待线程的返回值。
    返回值:
  • 成功返回0
  • 失败返回错误号

在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone().该系统调用copy了一个和原先进程完全一样的进程,并在这个进程中执行线程函数。不过这个copy过程和fork不同。copy后的进程和原先的进程共享了所有的变量,运行环境。这样,原先进程中的变量变动在copy后的进程中便能体现出来


pthread_exit()
函数作用:终止调用它的线程并返回一个指向某个对象的指针。
函数原型:void pthread_exit( void * value_ptr );
参数:
value_ptr:函数的返回代码。只要pthread_join的第二个参数value_ptr不是null,这个值就会被传递给value_ptr


pthread_yield()
函数原型:int pthread_yield(void);
函数作用: pthread_yield()导致调用线程放弃CPU。线程被放置在运行队列的末尾,以保持其静态优先级,并计划另一个线程运行。
返回值:

  • 成功返回0
  • 失败返回一个错误号8

pthread_self()
函数作用:获得线程自身的ID


gettimeofday()
作用:获取当前时间按
获取函数运行时间:函数运行后的时间-函数运行前的时间


pthread_kill()
函数原型:int pthread_kill(pthread_t thread, int sig)
函数作用:向指定ID的线程发送sig信号


sigaction()函数
函数原型:int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
函数作用:用来查询或设置信号处理方式
参数:

  • signum:指定要处理扽信号
  • act:指向信号动作结构的指针
  • oldact:指向信号动作结构的指针
struct sigaction {
    void (*sa_handler)(int);		//指向信号处理函数的地址
    void (*sa_sigaction)(int, siginfo_t *, void *);		//指向函数的指针
    sigset_t sa_mask;		
    int sa_flags;		//用于指示信号处理函数的不同选项,可以通过“|”连接不同的参数,从而实现所需的选项设置。
};

siginfo_t结构体:

struct siginfo_t {
    int si_signo;        //Signal number
    int si_errno;        //Errno value
    int si_code;         //Signal code
    pid_t si_pid;        //Sending process ID
    uid_t si_uid;        //Real user ID of sending process
    int si_status;       //Exit value or signal
    clock_t si_utime;    //User time consumed
    clock_t si_stime;    //System time consumed
    signal_t si_value;   //Signal value
    int si_int;          //POSIX.1b signal
    void *si_ptr;        //POSIX1.b signal
    void *si_addr;       //Memory location that caused fault
    int si_band;         //Band event
    int si_fd;           //File descriptor
};

pthread_attr_init()
函数原型:int pthread_attr_init(pthread_attr_t *attr);
函数作用:初始化一个线程对象的属性,需要用pthread_attr_destroy函数对其去除初始化。
参数:指向一个线程属性结构的指针,结构中的元素分别对应着新线程的运行属性。属性对象主要包括是否绑定、是否分离、堆栈地址和大小、优先级等。默认属性为非绑定、非分离、默认1MB堆栈、与父进程有相同优先级。
返回值:

  • 成功返回0
  • 失败返回错误代码

pthread_attr_destroy()
函数原型:int pthread_attr_destroy(pthread_attr_t *attr);
函数作用:销毁一个目标结构,并且使它在重新初始化之前不能重新使用。
参数:要删除的线程属性结构体指针
返回值:

  • 成功返回0
  • 错误返回错误代码



在这里插入图片描述
在这里插入图片描述
注意pthread_join函数的参数:
只要pthread_join的第二个参数value_ptr不是null,pthread_exit中的参数就会被传递给value_ptr。

注意在用循环进行创建线程且参数跟循环的层数有关的话有时会导致混乱,线程创建的快慢是不确定的,所以可能导致的所传过去的参数出现重复。

解决方法:
在每次创建完线程之后都睡眠一下。
将要传过去的参数先放在一个数组中。

多线程

可在控制线程中创建多个线程,若多个线程对控制线程所传过去的同一个参数进行修改,那么这个参数的地址空间就相当于这些线程的共享内存空间。
在这里插入图片描述

因为线程是在进程的堆栈空间中创建的,所以可以创建的线程数是有限。,可以分配给线程的空间也是有限的,接近2G。

线程池

线程池其实就是先创建能创建的所有线程,然后将没有使用到的线程放在线程池中等待,需要线程时就调用线程池中现有的线程。

注意:在运行时需要连接动态库foprnmp

在这里插入图片描述

fork() and exec()

如果在main()中调用fork(),子进程只会复制main()函数,而不复制其他线程的地址空间,
如果fork()是在其他线程中创建的,那么子进程只会复制该线程的地址空间。

若在其他进程中调用fork()会导致发生意外情况,如果该线程在退出之前没有保证子进程已经结束,那么就会导致该进程变成一个孤儿进程。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C11是一种C语言的标准,于2011年发布,是C语言的一个重要更新版本。C11引入了很多新的特性,包括一些新的关键字和函数,以及对线程支持的改进。然而,C11的线程支持非常基本,只提供了一个简单的线程,缺乏高级线程处理和同步机制。 POSIX是一种操作系统接口标准,定义了UNIX和类UNIX操作系统所需的API(应用程序编程接口)。 POSIX线程(也称为pthread)是一个标准线程,为开发多线程应用程序提供了一些常用的线程操作和同步机制。POSIX线程具有可移植性,并可以在各种操作系统上使用。 因此,C11的线程提供了一些基本的线程支持,但缺乏高级线程处理和同步机制。如果需要更强大的线程支持和同步机制,则可以使用POSIX线程。 ### 回答2: C 11和POSIX线程都是提供多线程编程支持的。 C11是C语言的一个标准,于2011年发布。它引入了一些新特性,其中包括线程支持。C11中的线程提供了创建、控制和同步线程的函数和数据类型。通过这些函数,我们可以创建和启动新线程,并且可以执行多线程的并发操作。此外,C11线程还提供了一些同步原语,如互斥锁、条件变量、原子操作等,方便线程之间的协作与同步。 POSIX(Portable Operating System Interface for UNIX)是一个面向UNIX和类UNIX系统的标准接口,其中也包含了一个线程,即POSIX线程POSIX线程定义了一组函数和数据类型,用于创建和管理线程。与C11类似,POSIX线程也提供了创建、控制和同步线程的功能。与C11不同的是,POSIX线程是跨平台的,可以在不同的操作系统上使用,而C11线程只能在支持C11标准的编译器上使用。 总之,C11和POSIX线程都是为了方便程序员进行多线程编程而设计的,提供了创建、控制和同步线程的一系列函数和数据类型。它们的主要区别在于C11线程是C语言标准的一部分,只能在支持C11标准的编译器上使用,而POSIX线程是一个跨平台的标准接口,可以在多个操作系统上使用。 ### 回答3: C 11是C语言的一个版本,于ISO/IEC标准在2011年发布。C 11引入了许多新特性和改进,其中包括对多线程编程的支持。 C 11的线程提供了一组用于创建和管理线程的函数。它包括线程的创建、启动、暂停、恢复和退出等操作。线程还提供了一些同步机制,如互斥锁、条件变量和原子操作,用于实现线程间的通信和协调。通过这些函数和同步机制,程序员可以方便地编写多线程的程序,实现并发执行和资源共享。 而POSIX线程是一种通用的线程接口,提供了一套标准化的API函数,用于多平台的线程编程。POSIX线程可以用于不同的操作系统和编程语言,包括C语言。它的设计目标是提供一致的线程编程接口,使得在不同的系统和环境下,能够使用类似的方式来创建、管理和同步线程。 C 11的线程在很大程度上借鉴了POSIX线程的设计思想和接口。它们都提供了一套用于线程编程的函数和同步机制,虽然具体的函数名称和参数可能不同,但功能和作用是相似的。 总结起来,C 11的线程POSIX线程都是用于多线程编程的工具集,它们提供了一套标准的接口和函数,方便程序员创建、管理和同步线程。通过使用这些,程序员可以编写出高效、可靠、可移植的多线程程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值