在传统的Unix模型中,当一个进程需要由另一个实体执行某件事时,该进程派生(fork)一个子进程,让子进程去进行处理。

Unix下的大多数网络服务器程序都是这么编写的,即父进程接受连接,派生子进程,子进程处理与客户的交互。

虽然这种模型很多年来使用得很好,但是fork时有一些问题:

1. fork是昂贵的。内存映像要从父进程拷贝到子进程,所有描述字要在子进程中复制等等。目前有的Unix实现使用一种叫做写时拷贝(copy-on-write)的技术,可避免父进程数据空间向子进程的拷贝。尽管有这种优化技术,fork仍然是昂贵的。

2. fork子进程后,需要用进程间通信(IPC)在父子进程之间传递信息。Fork之前的信息容易传递,因为子进程从一开始就有父进程数据空间及所有描述字的拷贝。但是从子进程返回信息给父进程需要做更多的工作。

线程有助于解决这两个问题。线程有时被称为轻权进程(lightweight process),因为线程比进程“轻权”,一般来说,创建一个线程要比创建一个进程快10~100倍。

一个进程中的所有线程共享相同的全局内存,这使得线程很容易共享信息,但是这种简易性也带来了同步问题。

一个进程中的所有线程不仅共享全局变量,而且共享:进程指令、大多数数据、打开的文件(如描述字)、信号处理程序和信号处置、当前工作目录、用户ID和组ID。

但是每个线程有自己的线程ID、寄存器集合(包括程序计数器和栈指针)、栈(用于存放局部变量和返回地址)、error、信号掩码、优先级。

在Linux中线程编程符合Posix.1标准,称为Pthreads。所有的pthread函数都以pthread_开头。

以下先讲述5个基本线程函数,在调用它们前均要包括pthread.h头文件。然后再给出用它们编写的一个TCP客户/服务器程序例子。

第一个函数:

int pthread_create (pthread_t *tid,const pthread_attr_t *attr,void *(*func)(void *),void *arg);

一个进程中的每个线程都由一个线程ID(thread ID)标识,其数据类型是pthread_t(常常是unsigned int)。如果新的线程

创建成功,其ID将通过tid指针返回。

每个线程都有很多属性:优先级、起始栈大小、是否应该是一个守护线程等等,当创建线程时,我们可通过初始化一个pthread_attr_t

变量说明这些属性以覆盖缺省值。我们通常使用缺省值,在这种情况下,我们将attr参数说明为空指针。

最后,当创建一个线程时,我们要说明一个它将执行的函数。线程以调用该函数开始,然 后或者显式地终止(调用pthread_exit) 或者隐式地终止(让该函数返回)。函数的地址由func参数指定,该函数的调用参数是一个指针arg,如果我们需要多个调用参数,我们必须将它们打包成一 个结构,然后将其地址当作唯一的参数传递给起始函数。

在func和arg的声明中,func函数取一个通用指针(void *)参数,并返回一个通用指针(void *),这就使得我们可以传递一个

指针(指向任何我们想要指向的东西)给线程,由线程返回一个指针(同样指向任何我们想要指向的东西)。

调用成功,返回0,出错时返回正Exxx值。Pthread函数不设置errno。

第二个函数:

int pthread_join(pthread_t tid,void **status);

该函数等待一个线程终止。把线程和进程相比,pthread_creat类似于fork,而pthread_join类似于waitpid。

我们必须要等待线程的tid,很可惜,我们没有办法等待任意一个线程结束。

如果status指针非空,线程的返回值(一个指向某个对象的指针)将存放在status指向的位置。

第三个函数;

pthread_t pthread_self(void);

线程都有一个ID以在给定的进程内标识自己。线程ID由pthread_creat返回,我们可以pthread_self取得自己的线程ID。

第四个函数:

int pthread_detach(pthread_t tid);

线程或者是可汇合的(joinable)或者是脱离的(detached)。当可汇 合的线程终止时,其线程ID和退出状态将保留,直到另外一个线程调用pthread_join。脱离的线程则像守护进程:当它终止时,所有的资源都释放, 我们不能等待它终止。如果一个线程需要知道另一个线程什么时候终止,最好保留第二个线程的可汇合性。

Pthread_detach函数将指定的线程变为脱离的。

该函数通常被想脱离自己的线程调用,如:pthread_detach (pthread_self ( ));

第五个函数:

void pthread_exit(void *status);

该函数终止线程。如果线程未脱离,其线程ID和退出状态将一直保留到调用进程中的某个其他线程调用pthread_join函数。

指针status不能指向局部于调用线程的对象,因为线程终止时这些对象也消失。

有两种其他方法可使线程终止:

1. 启动线程的函数(pthread_creat的第3个参数)返回。既然该函数必须说明为返回一个void指针,该返回值便是线程的终止状态。

2. 如果进程的main函数返回或者任何线程调用了exit,进程将终止,线程将随之终止。

以下给出一个使用线程的TCP回射客户/服务器的例子,完成的功能是客户端使用线程 给服务器发从标准输入得到的字符,并在主线程中将从服务器端返回的字符显示到标准输出,服务器端将客户端发来的数据原样返回给客户端,每一个客户在服务器 上对应一个线程。利用该程序框架,通过扩展客户端和服务器端的处理功能,可以完成多种基于多线程的客户机/服务器程序。该程序在RedHat 6.0和TurboLinux4.02下调试通过。

linux下的多线程,linux下的多线程相关推荐

  1. linux编写一个简单的端口扫描程序,小弟我在linux下写了个简单的多线程端口扫描程序,运行时出现有关问题,请问一下(2)...

    当前位置:我的异常网» Linux/Unix » 小弟我在linux下写了个简单的多线程端口扫描程序, 小弟我在linux下写了个简单的多线程端口扫描程序,运行时出现有关问题,请问一下(2) www. ...

  2. 转Linux多线程条件下的计数器 2011-11-15 00:00中国IT实验室佚名

    Linux多线程条件下的计数器 2011-11-15 00:00中国IT实验室佚名 字号:A+|A- 最近编码需要实现多线程环境下的计数器操作,统计相关事件的次数.下面是一些学习心得和体会.不敢妄称原 ...

  3. Linux内存技术分析(下)

    Linux内存技术分析(下) 五. 内存使用场景 out of memory 的时代过去了吗?no,内存再充足也不可任性使用. 1.内存的使用场景 · page管理 · slab(kmalloc.内存 ...

  4. linux msgrcv阻塞接收_linux下高并发服务器实现

    在做网络服务的时候tcp并发服务端程序的编写必不可少.tcp并发通常有几种固定的设计模式套路,他们各有优点,也各有应用之处.下面就简单的讨论下这几种模式的差异: 单进程,单线程 在accept之后,就 ...

  5. linux多线程_Java+Linux,深入内核源码讲解多线程之进程

    之前写了两篇文章,都是针对Linux这个系统的,为什么?我为什么这么喜欢写这个系统的知识,可能就是为了今天的内容多线程系列,现在多线程不是一个面试重点 啊,那如果你能深入系统内核回答这个知识点,面试官 ...

  6. linux svn 服务 关闭,Linux下启动、关闭SVN服务

    Linux下启动/关闭Oracle 一.Linux下启动Oracle Linux下启动Oracle分为两步: 1)启动监听: 2)启动数据库实例: 1.登录服务器,切换到oracle用户,或者以ora ...

  7. linux 服务器间通信,Linux 下的进程间通信:套接字和信号 | Linux 中国

    原标题:Linux 下的进程间通信:套接字和信号 | Linux 中国 学习在 Linux 中进程是如何与其他进程进行同步的. -- Marty Kalin 本篇是 Linux 下(IPC)系列的第三 ...

  8. linux c++开发_Linux/Windows下进行C/C++开发的差异

    1. 平台差异简介 Windows 和Unix是当前两大主流操作系统平台,基于C/C++的开发人员经常会面临这两个平台之间的移植的问题.Unix作为一个开发式的系统,其下有出现了很 多个分支,包括Su ...

  9. 技术精讲丨多线程环境下时间轮-海量定时任务的定时器设计

    多线程环境下海量定时任务处理-定时器设计 1.  定时器设计 2.  红黑树.最小堆以及跳表的实现对比 3.  时间轮的实现 视频讲解如下,点击观看: 技术精讲丨多线程环境下时间轮-海量定时任务的定时 ...

  10. 多线程环境下海量定时任务的定时器设计丨时间轮实现丨红黑树,跳表分析

    多线程环境下海量定时任务定时器设计 1. 定时器分析 2. 红黑树,最小堆,跳表实现比较分析 3. 时间轮实现 [Linux后端开发系列]多线程环境下海量定时任务的定时器设计丨时间轮实现丨红黑树,跳表 ...

最新文章

  1. 【Python刷题】_5
  2. 成功解决You are using pip version 9.0.3, however version 10.0.1 is available. You should consider upgr
  3. mysql数据库入门教程(15):流程控制结构
  4. Linux学习笔记(十五)用户和用户组
  5. 如何映射本地虚拟机或远程服务器磁盘到本地
  6. java 在已有的so基础上封装jni_webshell中的分离免杀实践java篇
  7. css如何调整红心样式_条码软件如何调整条码数据的样式
  8. 接收终端Request.InputStream阅读
  9. C#设计模式(11)-Composite Pattern
  10. 喜大普奔,FL Studio终于出官方中文版了!
  11. e5cc温控仪通讯参数设定_应用 | 如何实现S7300与S7200smart通讯?
  12. HTTP协议之Content-Encoding - 天下无贼 - 51CTO技术博客
  13. IANA已注册的TCP/UDP/SCTP/DCCP传输协议端口及服务名称
  14. 微信小程序(1)--注册及下载IDE
  15. 女生玩游戏什么款式蓝牙耳机好用?小清新高颜值游戏蓝牙耳机推荐
  16. 第7课:郭盛华课程_Linux系统的常用操作命令
  17. signal软件如何退出账号_微信怎么一键切换登录 微信多账号一键切换方法【图文详解】...
  18. 上海迪士尼推出“冰雪奇缘”梦幻仙境
  19. web前端期末大作业 基于HTML+CSS+JavaScript学生宿舍管理系统
  20. 常用数据清洗方法大盘点

热门文章

  1. member selection 运算符是什么
  2. 拓端tecdat|R语言进行相关矩阵分析及其网络可视化
  3. 拓端tecdat|R语言使用 LOWESS技术图分析逻辑回归中的函数形式
  4. python报表利器TableOne学习实践
  5. 为什么线程切换开销大
  6. 2021-06-22 超链接伪类
  7. 2021-06-20----CSS三种选择器
  8. truffle部署到测试网rinkeby
  9. git commit后,如何撤销commit
  10. kubernetes [ERROR Swap]: running with swap on is not supported. Please disable swap