Linux下创建所线程

2023-11-17

一. 线程

线程是轻量级的进程(LWP:light weight process),在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。操作系统会以进程为单位,分配系统资源,可以这样理解,进程是资源分配的最小单位,线程是操作系统调度执行的最小单位。

1.进程有自己独立的地址空间,多个线程共用同一个地址空间

线程更加节省系统资源,效率不仅可以保持的,而且能够更高
在一个地址空间中多个线程独享:每个线程都有属于自己的栈区,寄存器 (内核中管理的)
在一个地址空间中多个线程共享:代码段,堆区,全局数据区,打开的文件 (文件描述符表) 都是线程共享的

2.线程是程序的最小执行单位,进程是操作系统中最小的资源分配单位

每个进程对应一个虚拟地址空间,一个进程只能抢一个 CPU 时间片
一个地址空间中可以划分出多个线程,在有效的资源基础上,能够抢更多的 CPU 时间片

3.CPU 的调度和切换:线程的上下文切换比进程要快的多

 上下文切换:进程 / 线程分时复用 CPU 时间片,在切换之前会将上一个任务的状态进行保存,下次切换回这个任务的时候,加载这个状态继续运行,任务从保存到再次加载这个过程就是一次上下文切换。
线程更加廉价,启动速度更快,退出也快,对系统资源的冲击小。

4.在处理多任务程序的时候使用多线程比使用多进程要更有优势,但是线程并不是越多越好,如何控制线程的个数呢?

文件 IO 操作:文件 IO 对 CPU 是使用率不高,因此可以分时复用 CPU 时间片,线程的个数 = 2 * CPU 核心数 (效率最高)
处理复杂的算法 (主要是 CPU 进行运算,压力大),线程的个数 = CPU 的核心数 (效率最高)

二. 创建线程

每一个线程都有一个唯一的线程 ID,ID 类型为 pthread_t,这个 ID 是一个无符号长整形数,如果想要得到当前线程的线程 ID,可以调用如下函数:

pthread_t pthread_self(void);	// 返回当前线程的线程ID

在一个进程中调用线程创建函数,就可得到一个子线程,和进程不同,需要给每一个创建出的线程指定一个处理函数,否则这个线程无法工作。

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);
// Compile and link with -pthread, 线程库的名字叫pthread, 全名: libpthread.so libptread.a

参数:

thread: 传出参数,是无符号长整形数,线程创建成功,会将线程 ID 写入到这个指针指向的内存中

attr: 线程的属性,一般情况下使用默认属性即可,写 NULL

start_routine: 函数指针,创建出的子线程的处理动作,也就是该函数在子线程中执行。

arg: 作为实参传递到 start_routine 指针指向的函数内部
在这里插入代码片:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

 void  callback(void* arg)
{
    for(int i = 0; i < 5; i++  )
    {
         printf("子线程 : i = %ld\n",i);
    }  
    printf("子线程 : %ld\n",pthread_self());
    return NULL;
}

int main()
{
    pthread_t  tid;
    pthread_create(&tid ,  NULL , callback , NULL);    //callback 是一个回调函数
    for(int i = 0; i < 5; i++  )
    {
         printf("主线程 : i = %ld\n",i);
    }  
    printf("主线程 : %ld\n",pthread_self());
    sleep(3);    //睡眠3s
    return 0;
}

在这里插入图片描述

编译测试程序,会看到如下错误信息:

在这里插入代码片
$ gcc pthread_create.c 
/tmp/cctkubA6.o: In function `main':
pthread_create.c:(.text+0x7f): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

错误原因是因为编译器链接不到线程库文件(动态库),需要在编译的时候通过参数指定出来,动态库名为 libpthread.so 需要使用的参数为 -l,根据规则掐头去尾最终形态应该写成:-lpthread(参数和参数值中间可以有空格)。正确的编译命令为:

# pthread_create 函数的定义在某一个库中, 编译的时候需要加库名 pthread
$ gcc pp.c -lpthread -o app
$ ./app
子线程创建成功, 线程ID: 140310795798272
我是主线程, 线程ID: 140310804322112
i = 0
i = 1
i = 2
............

在打印的日志输出中为什么子线程处理函数没有执行完毕呢(只看到了子线程的部分日志输出)?
主线程一直在运行,执行期间创建出了子线程,说明主线程有 CPU 时间片,在这个时间片内将代码执行完毕了,主线程就退出了。子线程被创建出来之后需要抢cpu时间片, 抢不到就不能运行,如果主线程退出了, 虚拟地址空间就被释放了, 子线程就一并被销毁了。但是如果某一个子线程退出了, 主线程仍在运行, 虚拟地址空间依旧存在。

得到的结论:在没有人为干预的情况下,虚拟地址空间的生命周期和主线程是一样的,与子线程无关。

目前的解决方案:让子线程执行完毕,主线程再退出,可以在主线程中添加挂起函数 sleep();



本文转载作者:
作者: 苏丙榅
链接: https://subingwen.cn/linux/thread/#2-2-%E5%88%9B%E5%BB%BA%E7%BA%BF%E7%A8%8B

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux下创建所线程 的相关文章

  • 何时用引号将 shell 变量括起来?

    我应该或不应该在 shell 脚本中用引号括住变量吗 例如 下列说法正确的是 xdg open URL eq 2 or xdg open URL eq 2 如果是这样 为什么 一般规则 如果它可以为空或包含空格 或实际上任何空格 或特殊字符
  • 我想在 Red Hat Linux 服务器中执行 .ps1 powershell 脚本

    我有一个在窗口中执行的 ps1 powershell 脚本 但我的整个数据都在 Linux 服务器中 有什么可能的方法可以让我在红帽服务器中执行 powershell 脚本 powershell脚本是 Clear Host path D D
  • 如何获取与 shell 中的文件名模式匹配的所有文件的总文件大小?

    我正在尝试仅使用 shell 来计算与文件名模式匹配的所有文件 在目录树中 的总大小 以字节为单位 这是我到目前为止所拥有的 find name undo exec stat c s awk 总计 1 END 打印总计 有没有更简单的方法来
  • 在ubuntu中打开spyder

    我想在ubuntu中打开spyder Python IDE 通常我会在 shell 中编写 spyder 它会打开spyder IDE 现在 当我在shell中编写spyder时 它只是换行 什么也没有发生 类似于按 enter 我如何找回
  • MySQL 与 PHP 的连接无法正常工作

    这是我的情况 我正在尝试使用 Apache 服务器上的 PHP 文件连接到 MySQL 数据库 现在 当我从终端运行 PHP 时 我的 PHP 可以连接到 MySQL 数据库 使用 php f file php 但是当我从网页执行它时 它只
  • 为什么 OS X 和 Linux 之间的 UTF-8 文本排序顺序不同?

    我有一个包含 UTF 8 编码文本行的文本文件 mac os x cat unsorted txt foo foo 津 如果它有助于重现问题 这里是文件中确切字节的校验和和转储 以及如何自己生成文件 在 Linux 上 使用base64 d
  • bash while 循环的布尔表达式中的 -lt 意味着什么?

    我猜测它代表小于基于输出 但是我在哪里可以找到有关此语法的文档 bin bash COUNTER 0 while COUNTER lt 10 do echo The counter is COUNTER let COUNTER COUNTE
  • 链接错误:命令行中缺少 DSO

    我对 Linux 使用 Ubuntu 14 04 LTS 64 位 相当陌生 来自 Windows 并且正在尝试移植我现有的 CUDA 项目 当通过链接时 usr local cuda bin nvcc arch compute 30 co
  • 为什么此 NASM 代码会打印我的环境变量?

    本学期我刚刚完成计算机体系结构课程 除其他外 我们一直在涉足 MIPS 汇编并在 MARS 模拟器中运行它 今天 出于好奇 我开始在我的 Ubuntu 机器上摆弄 NASM 基本上只是将教程中的内容拼凑起来 并感受一下 NASM 与 MIP
  • 如何在 Linux 和 C 中使用文件作为互斥体?

    我有不同的进程同时访问 Linux 中的命名管道 并且我想让此访问互斥 我知道可以使用放置在共享内存区域中的互斥体来实现这一点 但作为一种家庭作业 我有一些限制 于是 我想到的是对文件使用锁定原语来实现互斥 我做了一些尝试 但无法使其发挥作
  • 如何并行执行4个shell脚本,我不能使用GNU并行?

    我有4个shell脚本dog sh bird sh cow sh和fox sh 每个文件使用 xargs 并行执行 4 个 wget 来派生一个单独的进程 现在我希望这些脚本本身能够并行执行 由于某些我不知道的可移植性原因 我无法使用 GN
  • /sys/device/ 和 dmidecode 报告的不同 CPU 缓存大小

    我正在尝试获取系统中不同缓存级别的大小 我尝试了两种技术 a 使用 sys device 中的信息 这是输出 cat sys devices system cpu cpu0 cache index1 size 32K cat sys dev
  • Python 3.4.3 subprocess.Popen 在没有管道的情况下获取命令的输出?

    我试图将命令的输出分配给变量 而不让命令认为它正在通过管道传输 原因是 如果正在通过管道传输 则相关命令会给出未格式化的文本作为输出 但如果从终端运行 则会给出颜色格式化的文本 我需要获取这种颜色格式的文本 到目前为止我已经尝试了一些事情
  • 如何在 Linux 上通过 FTP 递归下载文件夹 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 如何在不使用 IDE 的情况下在 Linux 上运行 Java 项目

    我是 Java 新手 基本上 我开发了一个java项目 其中包含Eclipse中的多个Java包 该项目在我安装了 redhat Linux 的桌面上运行正常 然而 我需要在一个更强大的没有安装X11的Linux服务器 redhat ent
  • vmsplice() 和 TCP

    在原来的vmsplice 执行 有人建议 http lwn net Articles 181169 如果您的用户态缓冲区是管道中可容纳的最大页面数的 2 倍 则缓冲区后半部分成功的 vmsplice 将保证内核使用缓冲区的前半部分完成 但事
  • Linux 中 m 标志和 o 标志将存储在哪里

    我想知道最近收到的路由器通告的 m 标志和 o 标志的值 从内核源代码中我知道存储了 m 标志和 o 标志 Remember the managed otherconf flags from most recently received R
  • 为什么 Linux 没有 DirectX API?

    在考虑现代显卡的 Windows 系统上 DirectX API 的驱动程序端实现时 我想知道为什么此实现在非 Windows 系统 尤其是 Linux 上不可用 由于明显缺乏此功能 我只能假设有一个我无视的充分理由 但在我的原始理解中 我
  • docker 非 root 绑定安装权限,WITH --userns-remap

    all 尝试让绑定安装权限正常工作 我的目标是在容器中绑定安装卷 以便 a 容器不以 root 用户身份运行入口点 二 docker daemon 配置了 userns remap 这样容器 主机上没有 root c 我可以绑定挂载和读 写
  • 如何为 Linux 桌面条目文件指定带有相对路径的图标?

    对于我的一个 Linux 应用程序 我有应用程序二进制文件 一个 launcher sh 脚本 针对 LD LIBRARY PATH 和一个 desktop 文件 所有这些都位于同一文件夹中 我想使用图标的相对路径而不是绝对路径 我试过了

随机推荐

  • H3 GPIO笔记

    NanoPi NEO Core最近买了一块 这个板子使用全志H3 查看H3的数据手册 把GPIO这部分做个笔记 H3有7组GPIO 如下 分别是PA PC PD PE PF PG PL 没有PB这一组 PA有22个端口 PC有19个端口 P
  • 【LeetCode题解】1475、商品折扣后的最终价格

    题目 给你一个数组 prices 其中 prices i 是商店里第 i 件商品的价格 商店里正在进行促销活动 如果你要买第 i 件商品 那么你可以得到与 prices j 相等的折扣 其中 j 是满足 j gt i 且 prices j
  • CSS动画:Transition与Animation

    本文总结CSS3中两个用来做动画的属性 一个是transition 另一个是animation 差异比较 CSS3 差异 transition 在给定的持续时间内平滑地更改属性值 从一个值到另一个值 也就是只需要指定开始与结束的参数 参数改
  • 让汽车的全景环视更智能更安全!

    随着现代汽车安全技术的进步 我们看到诸如全景环视等先进驾驶辅助 ADAS 技术成为现代汽车的新标准 本演示展示了如何通过精确的实时反射和AI来检测障碍 以提升全景环视系统的性能 让汽车驾驶更安全 尤其是 当全景环视系统内嵌Imaginati
  • cesium-添加点并且可以编辑

    完整代码
  • 05_Numpy任意行&列的删除方法(numpy.delete)

    05 Numpy任意行 列的删除方法 numpy delete 函数Numpy delete 可以删除ndarray数组中任意的行或者列 指定要删除的轴 维度 和要删除的位置 行号 列号 也可以通过切片或列表选择多个行或者列的编号 对以下的
  • 【Unity Shaders】抖音变身漫画1

    先来看一下手机拍出来的效果 我们发现有一张人像变成了卡通漫画脸 其它的只是做了一些图像处理 你可以再拍几张看一下 会发现千篇一律的大眼 小嘴有没有 你想的没错 这个是AI换脸技术 抖音特效里有很多了 把这个漫画脸再加上对图像的漫画处理 最后
  • 解读CUDA Compiler Driver NVCC - Ch.5

    前言 前面几篇文章 我们了解了NVCC的作用 nvcc编译的two stage 每个stage做了什么 怎么去选择虚拟架构和真实架构 JIT编译的原理 好处和弊端以及解决方案 本文我们将了解几个实际的nvcc编译命令 Base Notati
  • el-select中多选回显数据后没法重新选择和更改

    我用element select 多选回显的时候 回显正常 不能点击清除 不能选择改变数据 然后去搜了这篇文章文章链接 博主解释要在select标签上加一个强制渲染 如下图
  • Docker的网络模式

    目录 Docker的四种网络模式 1 Bridge 网络模式 类似于VMware的NAT模式 Bridge 网络模式介绍 bridge模式示意图 2 Host 网络模式 Host 网络模式介绍 Host模式示意图 3 Container 网
  • 【Redis】集合Set和底层实现

    文章目录 Redis 集合 Set Set简介 常用命令 应用场景 共同关注实例 整数集合 整数集合介绍 整数集合的升级 哈希表 哈希表的原理和实现 Redis中的哈希表 rehash 渐进式rehash Redis 集合 Set Set简
  • 如何用xp系统做服务器,xp系统如何做远程服务器呢

    xp系统如何做远程服务器呢 内容精选 换一换 网站的访问与云服务器的网络配置 端口通信 防火墙配置 安全组配置等多个环节相关联 任意一个环节出现问题 都会导致网站无法访问 本节操作介绍网站无法访问时的排查思路 网站无法访问怎么办 如果打开网
  • 14-5_Qt 5.9 C++开发指南_基于HTTP 协议的网络应用程序

    文章目录 1 实现高层网络操作的类 2 基于HTTP协议的网络文件下载 3 源码 3 1 可是化UI设计 3 2 mainwindow h 3 3 mainwindow cpp 1 实现高层网络操作的类 Qt 网络模块提供一些类实现 OSI
  • Synchronized的锁升级过程

    Synchronized的锁升级过程 synchronized锁升级过程 在synchronized中引入了偏向锁 轻量级锁 重量级锁之后 当前具体使用的是synchronzed中的那种类型锁 是根据线程竞争激烈程度来决定的 偏向锁 在锁对
  • vue使用luckysheet,引入图表chartmix,实现打印按钮功能

    1 下载Luckysheet源码 下载地址 https github com dream num Luckysheet 按照下载地址提示 npm run build 打包源码 生成dist文件夹 2 引入luckysheet的js文件和cs
  • TinyWebServer

    遇到的问题 1 Reactor和Proactor 当下开源软件能做到网络高性能的原因就是 I O 多路复用吗 是的 基本是基于 I O 多路复用 用过 I O 多路复用接口写网络程序的同学 肯定知道是面向过程的方式写代码的 这样的开发的效率
  • 数据可视化pyecharts绘制饼状图和环形图

    艰难做了新的作业练习 记录一下 from pyecharts import options as opts from pyecharts charts import Pie Page from pyecharts faker import
  • FC基本定义

    FC基本定义 虚拟化的软件有很多 华为开发的服务器虚拟化软件Fusioncompute CAN compute node agent 提供虚拟化功能 版本6 3之前是基于开源的xen开发的 6 3之后是基于开源的Kvm开发的 1 CAN V
  • 10月08日星期二 恒指/美原油/美黄金 走势分析

    财经早餐 2019年10月08日星期二 重点关注的财经数据与事件 07 50 日本8月贸易帐 09 45 中国9月财新服务业PMI 13 45 瑞士9月季调后失业率 14 00 德国8月季调后工业产出月率 14 45 法国8月贸易帐 18
  • Linux下创建所线程

    一 线程 线程是轻量级的进程 LWP light weight process 在 Linux 环境下线程的本质仍是进程 在计算机上运行的程序是一组指令及指令参数的组合 指令按照既定的逻辑控制计算机运行 操作系统会以进程为单位 分配系统资源