热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《UNIX网络编程卷1》笔记:线程

在非阻塞式IO一节中,我们使用fork实现了一个多进程TCP回射客户程序,使得父进程处理标准输入到套接字的数据,子进程处理套接字到标准输出的数据。voidstr_cli(FILE*fp,int

在非阻塞式I/O一节中,我们使用fork实现了一个多进程TCP回射客户程序,使得父进程处理标准输入到套接字的数据,子进程处理套接字到标准输出的数据。

void str_cli(FILE *fp, int sockfd)  
{
pid_t pid;
char sendline[MAXLINE], recvline[MAXLINE];

/*子进程 socket ---> stdout*/
if ((pid = Fork()) == 0) {
while (Readline(sockfd, recvline, MAXLINE) > 0)
Fputs(recvline, stdout);

/*子进程向父进程发送一个SIGTERM信号,以防止父进程继续运行*/
kill(getppid(), SIGTERM);
exit(0);
}
/*父进程stdin ---> socket*/
while (Fgets(sendline, MAXLINE, fp) != NULL)
Writen(sockfd, sendline, strlen(sendline));
Shutdown(sockfd, SHUT_WR);
pause();

return;
}
然而,这个程序有两个缺点:

 1. fork()调用非常昂贵,它要复制一个进程。

 2. 父子进程之间传递信息需要进程间通信(IPC)机制。

使用线程(也称作“轻量级进程”),我们就能避免这两个问题。一是因为创建一个线程往往比创建一个进程花费的时间要少的多,二是因为同一个进程内的所有线程都共享全局内存,这使得线程间通信非常容易。然而,易于共享信息也使得线程要面临我们后面要讲的“同步”问题。

下面给出Linux下线程库pthread常用的API:

#include 

/*创建一个线程*/
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);

/*等待一个线程退出*/
int pthread_join(pthread_t thread, void **retval);

/*使线程转为脱离状态*/
int pthread_detach(pthread_t thread);

/*返回线程ID*/
pthread_t pthread_self(void);

/*退出线程*/
void pthread_exit(void *value_ptr);
下面是相应的str_cli函数的多线程版本:

#include "unp.h"

void *copyto(void *);

static int sockfd;
static FILE *fp;

void str_cli(FILE *fp_arg, int sockfd_arg)
{
char recvline[MAXLINE];
pthread_t tid;

sockfd = sockfd_arg;
fp = fp_arg;

/*创建一个线程*/
Pthread_create(&tid, NULL, copyto, NULL);

while (Readline(sockfd, recvline, MAXLINE) > 0)
Fputs(recvline, stdout);
}

void *copyto(void *arg)
{
char sendline[MAXLINE];

while (Fgets(sendline, MAXLINE, fp) != NULL)
Writen(sockfd, sendline, strlen(sendline));

Shutdown(sockfd, SHUT_WR);

return NULL;
}

下面是使用多线程的TCP回射服务器程序:

#include "unp.h"

static void *doit(void *);

int main(int argc, char **argv)
{
int listenfd, *iptr; /*connfd;*/
pthread_t tid;
socklen_t addrlen, len;
struct sockaddr *cliaddr;

if (argc == 2)
listenfd = Tcp_listen(NULL, argv[1], &addrlen);
else if (argc == 3)
listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
else
err_quit("usage: tcpserv01 [ ] ");

cliaddr = Malloc(addrlen);

for ( ; ; ) {
len = addrlen;
iptr = Malloc(sizeof(int));
*iptr = Accept(listenfd, cliaddr, &len);
Pthread_create(&tid, NULL, &doit, iptr); /*为每个客户创建一个服务线程*/
}
}

static void *doit(void *arg)
{
int connfd;

cOnnfd= *((int*)arg);
free(arg);
/*调用pthread_detach函数让自身脱离,因为
主线程没有理由等待它创建的每个线程结束*/
Pthread_detach(pthread_self());
str_echo(connfd);
Close(connfd);

return NULL;
}
注意是如何将描述符通过参数传递给线程函数的。


推荐阅读
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
author-avatar
赵晓伟
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有