Linux多线程编程(二)——线程属性

pthread接口允许我们通过设置每个对象关联的不同属性来细调线程的行为。

在上一篇中我们调研pthread_create函数的实例中,传入的参数都是空指针,而不是指向pthread_attr_t结构的指针。可以使用pthread_attr_t结构修改线程默认 属性,并把这些属性和创建的线程联系起来。可以使用pthread_attr_init函数初始化pthread_attr_t。在调用pthread_attr_init以后,pthread_attr_t结构所包含的就是操作系统实现支持的所有线程属性的默认值。

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);

int pthread_attr_destroy(pthread_attr_t *attr);

			两个函数的返回值:若成功,返回0;否则,返回错误编号
如果要反初始化pthread_attr_t结构,可以调用pthread_attr_destroy函数。如果pthread_attr_init的实现对实现属性对象的内存空间是 动态分配的,pthread_attr_destroy就会释放该内存空间。除此之外,pthread_attr_destroy还会用无效的值初始化属性对象,因此,如果该属性对象被误用,将会导致pthread_create函数返回错误代码。
如果在创建线程时就知道不需要了解线程的终止状态,就可以修改pthread_attr_t结构中的detachstate设置成以下两个合法值之一:PTHREAD_CREATE_DETACHED,以分离状态启动线程;或者PTHREAD_CREATE_JOINABLE,正常启动线程,应用程序可以获取线程的终止状态。

#include <pthread.h>

int pthread_attr_getdetachstate(const pthread_attr_t *restrict attr,
				int *detachstate);

int pthread_attr_setdetachstate(pthread_attr_t *attr, int *detachstate)

			两个函数的返回值:若成功,返回0;否则,返回错误编号
可以调用pthread_attr_getdetachstate函数 获取当前的detachstate线程属性。第二个参数所指向的整数要么设置成PTHREAD_CREATE_DETACHED,要么设置成PTHREAD_CREATE_JOINABLE,具体要取决于给定 pthread_attr_t结构中的属性值。

可以使用函数pthread_attr_getstack和pthread_attr_setstack对线程栈属性进行管理。

#include <pthread.h>

int pthread_attr_getstack(const pthread_attr_t *restrict attr,
			  void **restrict stackaddr,
			  size_t *restrict stacksize);

int pthread_attr_setstack(pthread_attr_t *attr,
			  void *stackaddr, size_t stacksize);

			两个函数的返回值:若成功,返回0;否则,返回错误编号
对于进程来说,虚地址空间的大小是固定的。因为进程中只有一个栈,所以它的大小通常不是问题。但对于线程来说,同样大小的虚地址空间必须被所以的线程栈共享。如果应用程序使用了许多线程,以致这些线程栈的累计大小超过了可用的虚地址空间,就需要减少默认的线程栈大小。另一方面,如果线程调用的函数分配了大量的自动变量,或者调用的函数涉及许多很深的栈帧,那么需要的栈大小可能要比默认的大。

如果线程的虚地址空间都用完了,那可以使用malloc或者mmap来为可替代的栈分配空间,并用pthread_attr_setstack函数来改变新建线程的栈位置。由stackaddr参数指定的地址可以用作线程栈的内存范围中的最低可寻址地址,该地址与处理器结构相应的边界应对其。当然,这要假设malloc和mmap所用的虚地址范围与程序栈当前使用的虚地址范围不同。

stackaddr线程属性被定义为栈的最低内存地址,但这并不一定是栈的开始地址位置。对于一个给定的处理器结构来说,如果栈是从高地址向低地址方向增长的,那么stackaddr线程属性将是栈的结尾位置,而不是开始位置。

应用程序也可以通过pthread_attr_getstacksize和pthread_attr_setstacksize函数读取或设置线程属性stacksize。

#include <pthread.h>

int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,
			      size_t *restrict stacksize);

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

			两个函数的返回值:若成功,返回0;否则,返回错误编号
如果希望改变默认的栈大小,但又不想自己处理线程栈的分配问题,这时使用pthread_attr_setstacksize函数就非常有用。设置stacksize属性时,选择的stacksize不能小于PTHREAD_STACK_MIN。

线程属性guardsize控制着线程栈末尾之后用以避免栈溢出的扩展内存的大小。这个属性默认值是有具体实现来定义的,但常用值是系统页大小。可以把guardsize线程属性设置为0,不允许属性的这种特征行为发生:在这种情况下,不会提供警戒缓冲区。同样,如果修改了线程属性stackaddr,系统就认为我们将自己管理栈,进而使警戒缓冲区机制无效,这等同于把guardsize线程属性设置为0.

#include <pthread.h>

int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,
			      size_t *restrict guardsize);

int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);

			两个函数的返回值:若成功,返回0;否则,返回错误编号
如果guardsize线程属性被修改来了,操作系统可能会把它取为页大小的整数倍。如果线程的栈指针溢出到警戒区域,应用程序就可以通过信函接收到出错信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书全面介绍了UNIX系统的程序设计界面—系统调用界面和标准C库提供的许多函数。 本书的前15章着重于理论知识的阐述,主要内容包括UNIX文件和目录、进程环境、进程控制、 进程间通信以及各种I/O。在此基础上,分别按章介绍了多个应用实例,包括如何创建数据库函数库, PostScript 打印机驱动程序,调制解调器拨号器及在伪终端上运行其他程序的程序等。 本书内容丰富权威, 概念清晰精辟,一直以来被誉为UNIX编程的“圣经”,对于所有UNIX程序员—无论是初学者还是专家级人士 —都是一本无价的参考书籍。 目 录 译者序 译者简介 前言 第1章 UNIX基础知识 1 1.1 引言 1 1.2 登录 1 1.2.1 登录名 1 1.2.2 shell 1 1.3 文件和目录 2 1.3.1 文件系统 2 1.3.2 文件名 2 1.3.3 路径名 2 1.3.4 工作目录 4 1.3.5 起始目录 4 1.4 输入和输出 5 1.4.1 文件描述符 5 1.4.2 标准输入、标准输出和标准 出错 5 1.4.3 不用缓存的I/O 5 1.4.4 标准I/O 6 1.5 程序和进程 7 1.5.1 程序 7 1.5.2 进程和进程ID 7 1.5.3 进程控制 7 1.6 ANSI C 9 1.6.1 函数原型 9 1.6.2 类属指针 9 1.6.3 原始系统数据类型 10 1.7 出错处理 10 1.8 用户标识 11 1.8.1 用户ID 11 1.8.2 组ID 12 1.8.3 添加组ID 12 1.9 信号 12 1.10 UNIX时间值 14 1.11 系统调用和库函数 14 1.12 小结 16 习题 16 第2章 UNIX标准化及实现 17 2.1 引言 17 2.2 UNIX标准化 17 2.2.1 ANSI C 17 2.2.2 IEEE POSIX 18 2.2.3 X/Open XPG3 19 2.2.4 FIPS 19 2.3 UNIX实现 19 2.3.1 SVR4 20 2.3.2 4.3+BSD 20 2.4 标准和实现的关系 21 2.5 限制 21 2.5.1 ANSI C限制 22 2.5.2 POSIX限制 22 2.5.3 XPG3限制 24 2.5.4 sysconf、pathconf 和fpathconf 函数 24 2.5.5 FIPS 151-1要求 28 2.5.6 限制总结 28 2.5.7 未确定的运行时间限制 29 2.6 功能测试宏 32 2.7 基本系统数据类型 32 2.8 标准之间的冲突 33 2.9 小结 34 习题 34 第3章 文件I/O 35 3.1 引言 35 3.2 文件描述符 35 3.3 open函数 35 3.4 creat函数 37 3.5 close函数 37 3.6 lseek函数 38 3.7 read函数 40 3.8 write函数 41 3.9 I/O的效率 41 3.10 文件共享 42 3.11 原子操作 45 3.11.1 添加至一个文件 45 3.11.2 创建一个文件 45 3.12 dup和dup2函数 46 3.13 fcntl函数 47 3.14 ioctl函数 50 3.15 /dev/fd 51 3.16 小结 52 习题 52 第4章 文件和目录 54 4.1 引言 54 4.2 stat, fstat和lstat函数 54 4.3 文件类型 55 4.4 设置-用户-ID和设置-组-ID 57 4.5 文件存取许可权 58 4.6 新文件和目录的所有权 60 4.7 access函数 60 4.8 umask函数 62 4.9 chmod和fchmod函数 63 4.10 粘住位 65 4.11 chown, fchown和 lchown函数 66 4.12 文件长度 67 4.13 文件截短 68 4.14 文件系统 69 4.15 link, unlink, remove和rename 函数 71 4.16 符号连接 73 4.17 symlink 和readlink函数 76 4.18 文件的时间 76 4.19 utime函数 78 4.20 mkdir和rmdir函数

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值