线程基本操作(一)

一、简介

  使用线程函数库,需要引入头文件<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
");
            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 ...
");
        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
", 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 ",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
",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
",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;
}
原文地址:https://www.cnblogs.com/Malphite/p/7789979.html