创建一个新的线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
thread:返回线程ID
attr:设置线程的属性,attr为NULL表示使用默认属性。
start_toutine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数。
成功返回0,失败返回错误码;
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <unistd.h> #include <sys/types.h> #define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); }while(0) void* therad_routine(void *arg) { int i; for (i = 0; i < 20; ++i) { /* code */ printf("B"); fflush(stdout); } return 0; } int main(int argc, const char *argv[]) { pthread_t tid; int ret; ret = pthread_create(&tid, NULL, therad_routine, NULL); if(ret != 0) { fprintf(stderr, "pthread_create:%s\n", strerror(ret)); exit(EXIT_FAILURE); } int i; for (i = 0; i < 20; ++i) { /* code */ printf("A"); fflush(stdout); usleep(20); } sleep(1); return 0; }
当线程创建失败时, 错误信息会返回到errno中。
pthread同样也提供了线程内的而errno变量,一支持其他使用errno的代码,
对于pthreads函数的错误,简易通过返回值判定,因为赌气返回值要比赌气线程内的errno变量的开销更小。
打印结果
ABABABABABAB
可以看得出单核的情况下,主线程和线程之间是共享CPU时间片的。
它们是交替进行的。
ret = pthread_join(tid, NULL); if(ret != 0) { fprintf(stderr, "pthread_join:%s\n", strerror(ret)); exit(EXIT_FAILURE); }
主线程利用pthread_join来回收线程资源。
相对于多进程下僵尸进程的概念,多线程中也会产生僵尸线程。
所以我们可以使用pthread_detach来分离一个线程,这样便不会产生僵尸线程。
下面利用线程函数实现一个简单的回射服务器练习一下
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); }while(0) void* thread_routine(void* arg) { pthread_detach(pthread_self()); int conn = (int)arg; echo_sev(conn); printf("exiting thread ....\n"); return 0; } int main(int argc, const char *argv[]) { int listen = socket(PF_INET, SOCK_STREAM, 0); if(socket < 0 ) ERR_EXIT("socket"); struct sockaddr_in servraddr; servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); int on = 1; //设置端口复用 if(setsocketopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &ON, sizeof(on)) <0) ERR_EXIT("setsocketopt"); 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; int conn; while(1) { conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen); if(conn < 0) ERR_EXIT("accept"); printf("ip = %s, port = %d\n", inet_ntoa(peeraddr.sin_addr, ntohs(peeraddr.sin_port))); pthread_t tid; int ret; ret = pthread_create(&tid, NULL, thread_routine, (void*)conn); if(ret != 0) { fprintf(stderr, "pthread_create:%s\n", strerrno(ret)); exit(EXIT_FAILURE); } } return 0; }
注意点就是,要将创建的线程进行detrach,来避免僵尸线程的产生。
时间: 2024-11-07 22:45:51