POSIX 线程(一)
来源:互联网 发布:超市扫码枪软件费用 编辑:程序博客网 时间:2024/05/19 13:22
一. POSIX线程先关函数
POSIX线程库
与线程有关的函数构成一个完整的系列,绝大多数函数的名字都是以"pthread"打头的
要使用这些函数库,引入头文件<pthread.h>
连接这些线程函数库时要使用编译器命令的"-lpthread"选项
1. pthread_create函数
功能:创建一个新的线程
原型: int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
参数:
thread: 返回线程ID
attr: 设置线程的属性, attr为NULL 表示使用默认属性
start_routine: 是个函数地址,线程启动后要执行这个函数
arg : 传给线程启动后函数的参数
返回值: 成功返回0; 失败返回错误码
错误检查
(1) 传统一些函数是,成功返回0, 失败返回-1, 并且对全局变量 errno赋值以指示错误.
(2) pthreads 函数出错时不会设置全局变量 errno(而大部分其他POSIX函数会这样做).而是将错误代码通过返回值返回.
(3) pthreads 同样也提供了线程内的errno 变量,以支持其他使用 errno 的代码.对于 pthreads 函数的错误,建议通过返回值判定,因为读取返回值要比读取线程内的 errno 变量的开销更小.
2. pthread_exit 函数
功能: 线程终止
原型:
void pthread_exit(void * value_ptr);
参数:
value_ptr: value_ptr 不要指向一个局部变量.
返回值: 无返回值,和进程一样,线程结束的时候无法返回到它的调用者(自身)
3. pthread_join 函数
功能:等待线程结束
原型:
int pthread_join(pthread_t thread,void ** value_ptr);
参数:
thread: 线程ID
value_ptr : 它指向一个指针,后者指向线程的返回值
返回值: 成功返回0,失败返回错误码.
3. pthread_self 函数
功能: 返回线程ID
原型: pthread_t pthread_self(void);
返回值: 成功返回0
4. pthread_cancel 函数
功能: 取消一个执行中的线程
原型:
int pthread_cancel(pthread_t thread);
参数:
thread: 线程ID
返回值: 成功返回0, 失败返回错误码
5. pthread_detach 函数
功能: 将一个线程分离
原型:
int pthread_detach(pthread_t thread);
参数:
thread: 线程ID
二. 用线程实现回射客户/服务器程序
POSIX线程库
与线程有关的函数构成一个完整的系列,绝大多数函数的名字都是以"pthread"打头的
要使用这些函数库,引入头文件<pthread.h>
连接这些线程函数库时要使用编译器命令的"-lpthread"选项
1. pthread_create函数
功能:创建一个新的线程
原型: int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
参数:
thread: 返回线程ID
attr: 设置线程的属性, attr为NULL 表示使用默认属性
start_routine: 是个函数地址,线程启动后要执行这个函数
arg : 传给线程启动后函数的参数
返回值: 成功返回0; 失败返回错误码
错误检查
(1) 传统一些函数是,成功返回0, 失败返回-1, 并且对全局变量 errno赋值以指示错误.
(2) pthreads 函数出错时不会设置全局变量 errno(而大部分其他POSIX函数会这样做).而是将错误代码通过返回值返回.
(3) pthreads 同样也提供了线程内的errno 变量,以支持其他使用 errno 的代码.对于 pthreads 函数的错误,建议通过返回值判定,因为读取返回值要比读取线程内的 errno 变量的开销更小.
2. pthread_exit 函数
功能: 线程终止
原型:
void pthread_exit(void * value_ptr);
参数:
value_ptr: value_ptr 不要指向一个局部变量.
返回值: 无返回值,和进程一样,线程结束的时候无法返回到它的调用者(自身)
3. pthread_join 函数
功能:等待线程结束
原型:
int pthread_join(pthread_t thread,void ** value_ptr);
参数:
thread: 线程ID
value_ptr : 它指向一个指针,后者指向线程的返回值
返回值: 成功返回0,失败返回错误码.
3. pthread_self 函数
功能: 返回线程ID
原型: pthread_t pthread_self(void);
返回值: 成功返回0
4. pthread_cancel 函数
功能: 取消一个执行中的线程
原型:
int pthread_cancel(pthread_t thread);
参数:
thread: 线程ID
返回值: 成功返回0, 失败返回错误码
5. pthread_detach 函数
功能: 将一个线程分离
原型:
int pthread_detach(pthread_t thread);
参数:
thread: 线程ID
返回值: 成功返回0, 失败返回错误码
案例代码:
pthread.c
#include <unistd.h>#include <sys/types.h>#include <pthread.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \}while(0)void* thread_routine(void *arg){int i;for(i=0;i<20;i++){printf(" B ");fflush(stdout);usleep(20);if(i==3)pthread_exit("when i==3, pthread exit ");}sleep(3); //延迟子线程的结束 return 0;}int main(){pthread_t tid;int ret;// 错误信息通过函数返回if ( (ret = pthread_create(&tid,NULL,thread_routine,NULL)) !=0 ) { fprintf(stderr,"pthread_create:%s\n",strerror(ret)); exit(EXIT_FAILURE);}int i; /// 为主线程,打印字母 A for(i=0;i<20;++i){printf(" A ");fflush(stdout);// 刷新输出缓冲区usleep(20);}// 等待子线程的结束 void *value;if( (ret = pthread_join(tid,&value)) != 0){fprintf(stderr,"pthread_create:%s\n",strerror(ret));exit(EXIT_FAILURE);}printf("\n");printf("return message: %s\n",(char*)value);return 0;}
二. 用线程实现回射客户/服务器程序
#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pthread.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0)void echo_srv(int conn){ char recvbuf[1024]; while (1) { memset(recvbuf, 0, sizeof(recvbuf)); int ret = read(conn, recvbuf, sizeof(recvbuf)); if (ret == 0) { printf("client close\n"); break; } else if (ret == -1) ERR_EXIT("read"); fputs(recvbuf, stdout); write(conn, recvbuf, ret); } close(conn);}void *thread_routine(void *arg){ // 主线程没有调用pthread_join等待线程退出 //剥离线程,避免产生僵线程 int conn = (int)arg; // pthread_self 返回线程ID // pthread_detach 分离线程 pthread_detach(pthread_self()); int conn = *((int *)arg); // 将无类型指针强制转换成int* 指针 free(arg); // 取完值,free掉 echo_srv(conn); //每个线程处理一个连接,同一个进程没有可监听套接字 printf("exiting thread ...\n"); return NULL;}int main(void){ int listenfd; if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) ERR_EXIT("socket"); struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); int on = 1; if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) ERR_EXIT("setsockopt"); if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) ERR_EXIT("bind"); if (listen(listenfd, SOMAXCONN) < 0) ERR_EXIT("listen"); struct sockaddr_in peeraddr; socklen_t peerlen = sizeof(peeraddr); int conn; while (1) { if ((conn = accept(listenfd, (struct sockaddr *)&peeraddr, &peerlen)) < 0) ERR_EXIT("accept"); printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); pthread_t tid; //int ret; /*pthread_create(&tid, NULL, thread_routine, (void*)&conn);*/ // race condition问题,竟态问题 int *p = malloc(sizeof(int)); *p = conn; int ret; if ((ret = pthread_create(&tid, NULL, thread_routine,p)) != 0) //64位系统时指针不是4个字节,不可移植 , 所有使用malloc, { fprintf(stderr, "pthread_create:%s\n", strerror(ret)); exit(EXIT_FAILURE); } }}
1 0
- POSIX 线程(一)
- posix线程库<一>
- posix 线程(一)
- POSIX 线程详解(一)
- 第十二章 POSIX 线程(一)
- POSIX线程-条件变量(一)
- POSIX 线程编程指南(一)
- POSIX线程-条件变量(一)
- Posix 线程
- Posix线程
- POSIX线程
- POSIX 线程
- POSIX线程
- POSIX线程
- POSIX线程
- posix线程
- POSIX线程
- POSIX线程
- Unity3D优化总结(一)
- leetcode 208 【trie】
- 字典的相关操作
- LeetCode | Median of Two Sorted Arrays
- 大端小端的证明
- POSIX 线程(一)
- 我们iTailor智能衣橱项目想法v1.0
- 第14周-输入输出流,文本文件-项目1 - 小玩文件(2)
- Leetcode Longest Common Prefix (java)
- leetcode - Count Complete Tree Nodes
- AspNet MVC4 教学-27:Asp.Net MVC4 自定义helper及function的快速Demo
- List,Map在遍历的时候remove
- 索引的作用
- C#高级编程第一天