POSIX线程库复习

创建一个新的线程

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

POSIX线程库复习的相关文章

Linux posix线程库总结

由于历史原因,2.5.x以前的linux对pthreads没有提供内核级的支持,所以在linux上的pthreads实现只能采用n:1的方式,也称为库实现. 目前,pthreads的实现有3种方式: (1)第一,多对一,也就是库实现. (2)第二种,1:1模式. 1:1模式适合CPU密集型的机器.我们知道,进程(线程)在运行中会由于等待某种资源而阻塞,可能是I/O资源,也可能是CPU.在多CPU机器上1:1模式是个很不错的选择.因此1:1的优点就是,能够充分发挥SMP的优势. 这种模式也有它的缺

C/C++ Posix线程库的封装

经常没事写一些服务器压力测试的工具,如http,mysql,等.说到压力测试,首先想到的应该就是多线程,研究过一段时间的pthread,包括线程锁,在这里发一个自己写的Posix封装. Posix.h 该类作为一个父类,应写一个子类继承他,并重写action方法,action()为所有线程所执行的内容,最后使用Run()开始执行所有线程. #ifndef POSIX_H_ #define POSIX_H_ #include <iostream> #include <pthread.h&g

POSIX 线程详解(经典必看)

总共三部分: 第一部分:POSIX 线程详解                                   Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  2000 年 7 月 01 日 第二部分:通用线程:POSIX 线程详解,第 2部分       Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  20

POSIX线程(1)

POSIX线程库: 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以"pthread_"打头的 要使用这些函数库,要通过引入头文<pthread.h> 链接这些线程函数库时要使用编译器命令的"-lpthread"选项 pthread_create函数 功能:创建一个新的线程 原型 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_r

POSIX线程(2)

线程属性 初始化与销毁属性 int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr); 获取与设置分离属性 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); int pthread_attr_setdetachstate(pthread_attr_t *attr,

Posix线程编程指南(1)

Posix线程编程指南(1) 作者:杨沙洲 原文地址:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part1/ 线程创建与取消 这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第一篇将向您讲述线程的创建与取消. 1 线程创建 1.1 线程与进程 相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有

Posix线程编程指南(5)

Posix线程编程指南(5) 杨沙洲 原文地址:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part5/ 杂项 这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第五篇将向您讲述pthread_self().pthread_equal()和pthread_once()等杂项函数. 在Posix线程规范中还有几个辅助函数难以归类,暂且称其为杂项函数,主要包

Posix线程编程指南(4)

Posix线程编程指南(4) 杨沙洲 原文地址:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part4/ 线程终止 这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第四篇将向您讲述线程中止. 线程终止方式 一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退

POSIX 线程(一)

一. POSIX线程先关函数 POSIX线程库 与线程有关的函数构成一个完整的系列,绝大多数函数的名字都是以"pthread"打头的 要使用这些函数库,引入头文件<pthread.h> 连接这些线程函数库时要使用编译器命令的"-lpthread"选项 1. pthread_create函数 功能:创建一个新的线程 原型: int pthread_create(pthread_t *thread, const pthread_attr_t *attr, v