一、简介
使用线程函数库,需要引入头文件<pthread.h>
链接这些线程函数库时要使用编译命令的“ -lpthread” 选项
二、函数介绍
1、创建一个新的线程
原型
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;失败返回错误码
2、等待线程结束
原型
int pthread_join(pthread_t thread, void **retval);
参数
thread:线程ID
retval:指向一个指针,后者指向线程的返回值
返回值:
成功返回0;失败返回错误码
3、线程终止
原型
void pthread_exit(void *retval);
参数:
retval:不要指向一个局部变量
返回值:
无返回值,跟进程一样,线程结束的时候无法返回到他的调用者
4、返回 线程ID
原型:
pthread_t pthread_self(void);
返回值:
返回 线程ID
5、取消一个执行中的线程
原型:
int pthread_cancel(pthread_t thread);
参数:
thread:线程ID
返回值:
成功返回0;失败返回错误码
6、讲一个线程分离
原型:
int pthread_detach(pthread_t thread);
参数:
thread:线程ID
返回值:
成功返回0;失败返回错误码
使用线程实现回射客户/服务器程序:
echocli.c
#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.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_cli(int sock) { char sendbuf[1024] = {0}; char recvbuf[1024] ={0}; while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) { write(sock, sendbuf, strlen(sendbuf)); read(sock, recvbuf, sizeof(recvbuf)); fputs(recvbuf, stdout); memset(sendbuf, 0, sizeof(sendbuf)); memset(recvbuf, 0, sizeof(recvbuf)); } close(sock); } int main(void) { int sock; if ((sock = 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 = inet_addr("127.0.0.1"); if (connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) ERR_EXIT("connect"); echo_cli(sock); return 0; }
echosrv.c
#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); } } void* thread_routine(void *arg) { pthread_detach(pthread_self());//使用线程分离避免僵线程 int conn = *((int*)arg); free(arg); 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; int *p = malloc(sizeof(int)); *p = conn; //if((ret = pthread_create(&tid,NULL,thread_routine,(void*)conn)) != 0)不同系统int占用字节不同,不便于移植不同系统int占用字节不同,不便于移植 if((ret = pthread_create(&tid,NULL,thread_routine,p)) != 0) { fprintf(stderr,"pthread_create:%s\n",strerror(ret)); exit(1); } } return 0; }
线程传参方式:
#include <stdio.h> #include <pthread.h> #include <time.h> typedef struct _date{ int year; int mon; int day; }DATE; void thread_fun1(void *arg) { int num =*(int *)arg; free(arg); printf("num = %d\n",num); } void thread_fun2(void *arg) { DATE *date; date = (DATE *)arg; int year = date->year; int mon = date->mon; int day = date->day; free(arg); printf("date = %d: %d: %d\n",year,mon,day); } int main(void) { struct tm *local; time_t t; t=time(NULL); local=localtime(&t); pthread_t tid1,tid2; int *p = NULL; p = (int *)malloc(sizeof(int)); *p = 10; pthread_create(&tid1,NULL,thread_fun1,(void*)p); DATE *date; date = (DATE *)malloc(sizeof(DATE)); date->year = local->tm_year; date->mon = local->tm_mon; date->day = local->tm_mday; pthread_create(&tid2,NULL,thread_fun2,(void*)date); pthread_join(tid1,NULL); pthread_join(tid2,NULL); return 0; }