操作系统线程属性

线程属性

int pthread_create (pthread_t* restrict thread,const pthread_attr_t* restrict attr,void* (*start_routine) (void*),void* restrict arg);
​
//创建线程函数的第二个参数即为线程属性,传空指针表示使用缺省属性。
typedef struct {// 分离状态int detachstate;// PTHREAD_CREATE_DETACHED - 分离线程。// PTHREAD_CREATE_JOINABLE(缺省) - 可汇合线程。
​// 竞争范围int scope;// PTHREAD_SCOPE_SYSTEM - 在系统范围内竞争资源(时间片)。// PTHREAD_SCOPE_PROCESS(Linux不支持) - 在进程范围内竞争资源。​// 继承特性int inheritsched;// PTHREAD_INHERIT_SCHED(缺省) - 调度属性自创建者线程继承。// PTHREAD_EXPLICIT_SCHED - 调度属性由后面两个成员确定。​// 调度策略nt schedpolicy;// SCHED_FIFO - 先进先出策略。// 没有时间片。// 一个FIFO线程会持续运行,直到阻塞或有高优先级线程就绪。// 当FIFO线程阻塞时,系统将其移出就绪队列,待其恢复时再加到同优先级就绪队列的末尾。// 当FIFO线程被高优先级线程抢占时,它在就绪队列中的位置不变。// 因此一旦高优先级线程终止或阻塞,被抢占的FIFO线程将会立即继续运行。// SCHED_RR - 轮转策略。// 给每个RR线程分配一个时间片,一但RR线程的时间片耗尽,系统即将移到就绪队列的末尾。// SCHED_OTHER(缺省) - 普通策略。// 静态优先级为0。任何就绪的FIFO线程或RR线程,都会抢占此类线程。    
​// 调度参数struct sched_param schedparam;// struct sched_param {//     int sched_priority; /* 静态优先级 */// };​// 栈尾警戒区大小(字节)  缺省一页(4096字节)。size_t guardsize;
​// 栈地址void* stackaddr;
​// 栈大小(字节)size_t stacksize;
} pthread_attr_t;
​
注意:不要手动读写该结构体,而应调用pthread_attr_set/get函数设置/获取具体属性项。
设置线程属性:
初始化线程属性结构体:
pthread_attr_t attr = {}; // 不要使用这种方式
int pthread_attr_init (pthread_attr_t* attr);
设置具体线程属性项:
int pthread_attr_setdetachstate (pthread_attr_t* attr,int detachstate);
int pthread_attr_setscope (pthread_attr_t* attr,int scope);
int pthread_attr_setinheritsched (pthread_attr_t* attr,int inheritsched);
int pthread_attr_setschedpolicy (pthread_attr_t* attr,int policy);
int pthread_attr_setschedparam (pthread_attr_t* attr,const struct sched_param* param);
int pthread_attr_setguardsize (pthread_attr_t* attr,size_t guardsize);
int pthread_attr_setstackaddr (pthread_attr_t* attr,void* stackaddr);
int pthread_attr_setstacksize (pthread_attr_t* attr,size_t stacksize);
int pthread_attr_setstack (pthread_attr_t* attr,void* stackaddr, size_t stacksize);
以设置好的线程属性结构体为参数创建线程:
int pthread_create (pthread_t* restrict thread,const pthread_attr_t* testrict attr,void* (*start_routine) (void*),void* restrict arg);
销毁线程属性结构体:
int pthread_attr_destroy (pthread_attr_t* attr);
获取线程属性:
获取线程属性结构体:
int pthread_getattr_np (pthread_t thread,pthread_attr_t* attr);
获取具体线程属性项:
int pthread_attr_getdetachstate (pthread_attr_t* attr,int* detachstate);
int pthread_attr_getscope (pthread_attr_t* attr,int* scope);
int pthread_attr_getinheritsched (pthread_attr_t* attr,int* inheritsched);
int pthread_attr_getschedpolicy (pthread_attr_t* attr,int* policy);
int pthread_attr_getschedparam (pthread_attr_t* attr,struct sched_param* param);
int pthread_attr_getguardsize (pthread_attr_t* attr,size_t* guardsize);
int pthread_attr_getstackaddr (pthread_attr_t* attr,void** stackaddr);
int pthread_attr_getstacksize (pthread_attr_t* attr,size_t* stacksize);
int pthread_attr_getstack (pthread_attr_t* attr,void** stackaddr, size_t* stacksize);
以上所有函数成功返回0,失败返回错误码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define __USE_GNU
#include <pthread.h>
​
int printattrs (pthread_attr_t* attr) 
{printf("------- 线程属性 -------\n");
​int detachstate;int error = pthread_attr_getdetachstate (attr, &detachstate);if (error) {fprintf (stderr, "pthread_attr_getdetachstate: %s\n",strerror (error));return -1;}printf("分离状态:  %s\n",(detachstate == PTHREAD_CREATE_DETACHED) ? "分离线程" :(detachstate == PTHREAD_CREATE_JOINABLE) ? "可汇合线程" :"未知");
​int scope;if ((error = pthread_attr_getscope (attr, &scope)) != 0) {fprintf (stderr, "pthread_attr_getscope: %s\n",strerror (error));return -1;}printf ("竞争范围:  %s\n",(scope == PTHREAD_SCOPE_SYSTEM)  ? "系统级竞争" :(scope == PTHREAD_SCOPE_PROCESS) ? "进程级竞争" : "未知");
​int inheritsched;if ((error = pthread_attr_getinheritsched (attr,&inheritsched)) != 0) {fprintf (stderr, "pthread_attr_getinheritsched: %s\n",strerror (error));return -1;}printf ("继承特性:  %s\n",(inheritsched == PTHREAD_INHERIT_SCHED)  ? "继承调用属性" :(inheritsched == PTHREAD_EXPLICIT_SCHED) ? "显式调用属性" :"未知");
​int schedpolicy;if ((error = pthread_attr_getschedpolicy(attr,&schedpolicy)) != 0) {fprintf (stderr, "pthread_attr_getschedpolicy: %s\n",strerror (error));return -1;}printf ("调度策略:  %s\n",(schedpolicy == SCHED_OTHER) ? "普通" :(schedpolicy == SCHED_FIFO)  ? "先进先出" :(schedpolicy == SCHED_RR)    ? "轮转" : "未知");
​struct sched_param schedparam;if ((error = pthread_attr_getschedparam (attr, &schedparam)) != 0) {fprintf (stderr, "pthread_attr_getschedparam: %s\n",strerror (error));return -1;}printf ("调度优先级:%d\n", schedparam.sched_priority);
​size_t guardsize;if ((error = pthread_attr_getguardsize(attr, &guardsize)) != 0) {fprintf (stderr, "pthread_attr_getguardsize: %s\n",strerror (error));return -1;}printf ("栈尾警戒区:%u字节\n", guardsize);/*void* stackaddr;if ((error = pthread_attr_getstackaddr (attr, &stackaddr)) != 0) {fprintf (stderr, "pthread_attr_getstackaddr: %s\n",strerror (error));return -1;}printf ("栈地址:    %p\n", stackaddr);
​size_t stacksize;if ((error = pthread_attr_getstacksize (attr, &stacksize)) != 0) {fprintf (stderr, "pthread_attr_getstacksize: %s\n",strerror (error));return -1;}printf ("栈大小:    %u字节\n", stacksize);*/void* stackaddr;size_t stacksize;if ((error = pthread_attr_getstack (attr, &stackaddr,&stacksize)) != 0) {fprintf (stderr, "pthread_attr_getstack: %s\n",strerror (error));return -1;}printf ("栈地址:    %p\n", stackaddr);printf ("栈大小:    %u字节\n", stacksize);
​printf("------------------------\n");
​return 0;
}
​
void* thread_proc (void* arg) 
{pthread_attr_t attr;int error = pthread_getattr_np (pthread_self (), &attr);if (error) {fprintf (stderr, "pthread_getattr_np: %s\n", strerror (error));exit (EXIT_FAILURE);}
​if (printattrs (&attr) < 0)exit (EXIT_FAILURE);
​exit (EXIT_SUCCESS);
​return NULL;
}
​
int main (int argc, char* argv[]) 
{int error;pthread_attr_t attr, *pattr = NULL;
​if (argc > 1) {if (strcmp (argv[1], "-s")) {fprintf (stderr, "用法:%s [-s]\n", argv[0]);return -1;}
​if ((error = pthread_attr_init (&attr)) != 0) {fprintf (stderr, "pthread_attr_init: %s\n",strerror (error));return -1;}
​if ((error = pthread_attr_setdetachstate (&attr,PTHREAD_CREATE_DETACHED)) != 0) {fprintf (stderr, "pthread_attr_setdetachstate: %s\n",strerror (error));return -1;}
​if ((error = pthread_attr_setinheritsched (&attr,PTHREAD_EXPLICIT_SCHED)) != 0) {fprintf (stderr, "pthread_attr_setinheritsched: %s\n",strerror (error));return -1;}
​if ((error = pthread_attr_setstacksize (&attr, 4096*10)) != 0) {fprintf (stderr, "pthread_attr_setstack: %s\n",strerror (error));return -1;}
​pattr = &attr;}
​pthread_t tid;if ((error = pthread_create (&tid, pattr, thread_proc,NULL)) != 0) {fprintf (stderr, "pthread_create: %s\n", strerror (error));return -1;}
​if (pattr){if ((error = pthread_attr_destroy (pattr)) != 0) {fprintf (stderr, "pthread_attr_destroy: %s\n",strerror (error));return -1;}}
​pause ();return 0;
}

注意:如果man手册查不到线程的相关函数,安装完整版gnu手册:sudo apt-get install glibc-doc。

练习:实现大文件的多线程cp拷贝,对比系统cp命令,哪个速度更快,为什么?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/types.h>
​
typedef struct Task
{char* src;char* dest;size_t start;size_t end;
}Task;
​
void* run(void* arg)
{Task* task = arg;
​// 打开源文件和目标文件FILE* src_fp = fopen(task->src,"r");FILE* dest_fp = fopen(task->dest,"a");if(NULL == src_fp || NULL == dest_fp){perror("fopen");return NULL;}
​// 调整文件的位置指针fseek(src_fp,task->start,SEEK_SET);fseek(dest_fp,task->start,SEEK_SET);
​// 创建缓冲区char buf[1024];size_t buf_size = sizeof(buf);
​for(int i=task->start; i<task->end; i+=buf_size){int ret = fread(buf,1,buf_size,src_fp);if(0 >= ret)break;fwrite(buf,1,ret,dest_fp);}
​fclose(src_fp);fclose(dest_fp);free(task);
}
​
int main(int argc,const char* argv[])
{if(3 != argc){puts("Use:./cp <src> <dest>");return 0;}
​// 获取到文件的大小struct stat buf;if(stat(argv[1],&buf)){perror("stat");return -1;}
​// 创建出目标文件if(NULL == fopen(argv[2],"w")){perror("fopen");return -2;}
​// 计算需要的线程数量,以100M为单位size_t pthread_cnt = buf.st_size/(1024*1024*100)+1;
​// 分配任务pthread_t tid;for(int i=0; i<pthread_cnt; i++){Task* task = malloc(sizeof(Task));task->src = (char*)argv[1];task->dest = (char*)argv[2];task->start = i*1024*1024*100;task->end = (i+1)*1024*1024*100;
​// 创建子线程并分配任务pthread_create(&tid,NULL,run,task);
​// 分享子线程pthread_detach(tid);}// 结束主线程pthread_exit(NULL);
}

多线程并不能提高运行速度,反而可能会降低,所以多线程不适合解决运算密集性问题,而是适合解决等待、阻塞的问题,如果使用进程去等待,会浪费大量资源,所以使用更轻量的线程去等待,节约资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/51442.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【应用开发】解决正点原子I.MX6ull应用编程zlib移植问题

问题描述 在正点原子应用开发移植zlib库的时候&#xff0c;文档中有这样一段描述&#xff0c;先删除开发板中的zlib库&#xff0c;然后再拷贝zlib库 这就会导致在使用scp命令拷贝编译好的zlib库的时候报错没有zlib.so.1&#xff0c;如下图所示&#xff1a; 解决方法 千万不…

《算法竞赛进阶指南》0x27A*

如果给定一个“目标状态”&#xff0c;需要求出从初态到目标状态的最小代价&#xff0c;那么优先队列BFS的“优先策略”显然不完善。一个状态的当前代价最小&#xff0c;只能说明从起始状态到当前状态得到代价很小&#xff0c;而在未来的搜索中&#xff0c;从该状态到目标状态可…

安卓好软-----手机端提取apk的小工具 方便简单 无需root权限

apk提取工具 工具小巧。可以提取手机上面当前安装的apk和系统应用apk。而且无需root权限即可正常使用。 效果非常不错。比其他工具提取系统app方便好使。 下载&#xff1a;https://download.csdn.net/download/mg668/89683199?spm1001.2014.3001.5503

探索贪心算法:解决优化问题的高效策略

贪心算法是一种在每一步选择中都采取当前最佳选择的算法&#xff0c;以期在整体上达到最优解。它广泛应用于各种优化问题&#xff0c;如最短路径、最小生成树、活动选择等。本文将介绍贪心算法的基本概念、特点、应用场景及其局限性。 贪心算法的基本概念 贪心算法的核心思想是…

详解ACL限制SSH、Telnet远程登录及抓包实验

要求&#xff1a;lsw5只能lsw6登录&#xff0c;lsw6只能PC2登录 <Huawei>sys [Huawei]sysname sw2 [sw2]int vlanif1 [sw2-Vlanif1]ip address 192.168.10.2 24 [sw2-Vlanif1]q [sw2] <Huawei>sys [Huawei]sysname sw1 [sw1]int vlanif1 [sw1-Vlanif1]ip address …

动态代理IP的适用范围与优势分析

1. 什么是动态代理IP&#xff1f; 动态代理IP是一种在每次连接时更换IP地址的代理服务。与静态代理IP不同&#xff0c;动态代理IP会在每次访问时分配一个新的IP地址&#xff0c;或在设定的时间间隔内自动更换。这种机制使得动态代理IP非常适合需要频繁更换IP的应用场景。 2. …

视频单条剪、脚本靠手写?云微客开启海量视频时代

老板们注意了&#xff0c;现在已不再是视频单条剪&#xff0c;脚本靠手写的时代&#xff01;在这个信息爆炸的时代&#xff0c;短视频已经成为了现代信息传播和娱乐消费的重要载体&#xff0c;那么我们该如何高效、快速地制作出大量高质量的短视频内容呢&#xff1f;这就需要云…

面试必备:接口自动化测试精选面试题大全

一、 请问你是如何做接口测试的&#xff1f; 大体来说&#xff0c;经历以下过程&#xff1a;接口需求调研、接口测试工具选择、接口测试用例编写、接口测试执行、接口测试回归、接口测试自动化持续集成。具体来说&#xff0c;接口测试流程分成以下九步&#xff1a; 第一步&am…

SpringBoot集成kafka开发-消息消费的分区策略(消费者如何判断从哪个分区中消费消息的?)

这里写目录标题 1、kafak消息者消费消息的4种分区策略2、kafka默认的消费分区策略1-RangeAssignor&#xff08;均匀分配、默认分配策略&#xff09;2.1、代码验证RangeAssignor的消息分区策略2.1.1、消费者2.1.2、生产者2.1.3、kafak配置类2.1.4、对象实体类2.1.5、项目配置文件…

基于vue框架的病床管理信息系统odt4v(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 开题报告内容 基于Vue框架的病床管理信息系统开题报告 一、引言 随着医疗技术的不断进步和人口老龄化的加剧&#xff0c;医院面临着日益增长的医疗服务需求。病床作为医院资源的重要组成部分&#xff0c;其管理效率直接影响到患者的就医体验和医院的运营效…

Elasticsearch(面试篇)

目录 Elasticsearch的倒排索引是什么&#xff1f; 详细描述一下Elasticsearch更新和删除文档的过程 描述一下Elasticsearch搜索的过程 兄弟们一起加油 &#xff01; &#xff01; &#xff01; Elasticsearch的倒排索引是什么&#xff1f; 传统我们索引通过文章&#xff0c…

TCP/UDP的对比,粘包分包抓包,http协议

服务器端&#xff1a; 一、loop 127.0.0.1本地回环测试地址 二、tcp特点 面向连接、可靠传输、字节流 粘包问题&#xff1a;tcp流式套接字&#xff0c;数据与数据之间没有套接字&#xff0c;导致可能多次的数据粘到一起 解决方法&#xff1a;&#xff08;1&#xff09;规…

使用USB转485转接器,从机不响应

在调试485通信时&#xff0c;bms不响应主机&#xff0c;usb转485转换器接收指示灯常亮&#xff0c;现象如下&#xff0c;通过更新驱动程序解决。 更新驱动程序链接&#xff1a; 1. 下载并解压驱动文件 https://www.szutek.com/Uploads/file/20210917/20210917091627_42822.rar…

生信圆桌:专业生信服务器与平台服务的提供者

生信圆桌是一个专注于提供生物信息学&#xff08;生信&#xff09;服务器和平台服务的领先企业&#xff0c;致力于为全球科研机构、企业和独立研究者提供高性能的生信分析解决方案。随着生物信息学研究对计算资源的需求日益增加&#xff0c;生信圆桌凭借其先进的服务器技术和专…

C++ 多线程(互斥锁、条件变量)

互斥锁 最简单示例&#xff1a; #include <iostream> #include <thread> #include <mutex>std::mutex mtx; int counter 0;void increment() {for (int i 0; i < 10000; i) {// b1 是创建出来的对象. lock_guard 类似智能指针一样,为了防止忘记释放锁…

【QT学习】1-2 Liunx环境下QT5.12.9软件安装1——VMware17.0.0虚拟机安装

注意&#xff1a;如果电脑已经安装低版本的VMware&#xff0c;千万不要卸载&#xff0c;直接覆盖安装&#xff0c;更新到新的安装版本 1.点击.exe文件&#xff0c;右键以管理员身份运行&#xff0c;点击下一步&#xff0c;下一步 2.选择软件安装位置后&#xff0c;点击下一步。…

手写Spring框架(简单实现)

Spring风格的三级缓存管理&#xff1a;一个简单实现示例 在实现一个简单的Spring风格的依赖注入容器时&#xff0c;我们通常需要处理Bean的生命周期&#xff0c;包括实例化、属性注入以及完全初始化。为了处理复杂的依赖关系和循环依赖问题&#xff0c;我们可以使用三级缓存机…

虚幻5|制作一个木桩,含血量及伤害数字

一&#xff0c;基础设置 1.创建Actor蓝图类 2.编辑胶囊体和网格体的碰撞预设 3.打开敌人的角色蓝图&#xff0c;编辑飙血特效 二&#xff0c;创建敌人血量的ui&#xff0c;命名为敌人血量&#xff0c;如下 1. 2&#xff0c;打开后&#xff0c;添加一个画布画板和进度条&#…

ArkUI-布局(一)

ArkUI-布局 布局概述布局元素的组成如何选择布局布局位置对子元素的约束 线性布局部分属性与使用方式 层叠布局部分属性与使用方式 弹性布局基本概念布局方向布局换行主轴对齐方式交叉轴对齐方式容器设置交叉轴对齐方式子元素设置交叉轴对齐方式内容对齐 自适应拉伸 布局概述 …

C++基础面试题 | 什么是C++的列表初始化?

青山相待&#xff0c;白云相爱&#xff0c;梦不到紫罗袍共黄金带。 - 《山坡羊道情》(宋方壶) 2024.8.26 回答重点 C11中引入了列表初始化&#xff0c;其语法是用花括号{}来初始化变量或对象。列表初始化可以应用于&#xff1a; 基础数据类型用户自定义类型&#xff08;类、结…