`
brxonline
  • 浏览: 63891 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

UNIX编程(12)-线程控制

    博客分类:
  • C
 
阅读更多

1.线程限制

某些系统有线程的限制,可以通过sysconf函数来查询

2.线程属性

如想修改线程的属性,则可以在pthread_create调用时,传递pthread_attr_t类型指针参数

 

 

 

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);

int pthread_attr_destroy(pthread_attr_t   *attr);

 

Both return: 0 if OK, error number on failure


1)设置线程的分离状态

 

#include <pthread.h>

int pthread_attr_getdetachstate(const
 pthread_attr_t *restrict attr,
                                int *detachstate);

int pthread_attr_setdetachstate(pthread_attr_t
 *attr, int detachstate);

 

Both return: 0 if OK, error number on failure


例:以分离的状态创建线程

#include "apue.h"
#include <pthread.h>

int
makethread(void *(*fn)(void *), void *arg)
{
    int             err;
    pthread_t       tid;
    pthread_attr_t  attr;

    err = pthread_attr_init(&attr);
    if (err != 0)
        return(err);
    err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (err == 0)
        err = pthread_create(&tid, &attr, fn, arg);
    pthread_attr_destroy(&attr);
    return(err);
}


2)线程栈的操作接口

 

#include <pthread.h>

int pthread_attr_getstack(const pthread_attr_t
 *restrict attr,
                          void **restrict stackaddr,
                          size_t *restrict stacksize);

int pthread_attr_setstack(const pthread_attr_t *attr,
                          void *stackaddr, size_t
 *stacksize);

 

Both return: 0 if OK, error number on failure

 

 

#include <pthread.h>

int pthread_attr_getstacksize(const pthread_attr_t
 *restrict attr,
                              size_t *restrict
stacksize);

int pthread_attr_setstacksize(pthread_attr_t *attr
, size_t stacksize);

 

Both return: 0 if OK, error number on failure

3)guardsize,线程栈末尾之后用以避免栈溢出的扩展内存区

 

#include <pthread.h>

int pthread_attr_getguardsize(const pthread_attr_t
 *restrict attr,
                              size_t *restrict
guardsize);

int pthread_attr_setguardsize(pthread_attr_t *attr
, size_t guardsize);

 

Both return: 0 if OK, error number on failure


4)并发度

 

 

#include <pthread.h>

int pthread_getconcurrency(void);

 

Returns: current concurrency level

 

int pthread_setconcurrency(int level);

 

Returns: 0 if OK, error number on failure


3.同步属性

1)互斥量属性

 

#include <pthread.h>

int pthread_mutexattr_init(pthread_mutexattr_t *attr);

int pthread_mutexattr_destroy(pthread_mutexattr_t
 *attr);

 

Both return: 0 if OK, error number on failure


主要注意进程共享属性和类型属性

 

#include <pthread.h>

int pthread_mutexattr_getpshared(const
 pthread_mutexattr_t *
                                 restrict attr,
                                 int *restrict
pshared);

int pthread_mutexattr_setpshared
(pthread_mutexattr_t *attr,
                                 int pshared);

 

Both return: 0 if OK, error number on failure

 

#include <pthread.h>

int pthread_mutexattr_gettype(const
 pthread_mutexattr_t *
                              restrict attr, int
 *restrict type);

int pthread_mutexattr_settype(pthread_mutexattr_t
 *attr, int type);

 

Both return: 0 if OK, error number on failure


例:使用递归锁

#include "apue.h"
#include <pthread.h>
#include <time.h>
#include <sys/time.h>

extern int makethread(void *(*)(void *), void *);

struct to_info {
    void    (*to_fn)(void *);    /* function */
    void    *to_arg;             /* argument */
    struct timespec to_wait;     /* time to wait */
};

#define SECTONSEC  1000000000    /* seconds to nanoseconds */
#define USECTONSEC 1000          /* microseconds to nanoseconds */

void *
timeout_helper(void *arg)
{
    struct to_info *tip;

    tip = (struct to_info *)arg;
    nanosleep(&tip->to_wait, NULL);
    (*tip->to_fn)(tip->to_arg);
    return(0);
}

void
timeout(const struct timespec *when, void (*func)(void *), void *arg)
{
    struct timespec now;
    struct timeval  tv;
    struct to_info  *tip;
    int             err;

    gettimeofday(&tv, NULL);
    now.tv_sec = tv.tv_sec;
    now.tv_nsec = tv.tv_usec * USECTONSEC;
    if ((when->tv_sec > now.tv_sec) ||
      (when->tv_sec == now.tv_sec && when->tv_nsec > now.tv_nsec)) {
        tip = malloc(sizeof(struct to_info));
        if (tip != NULL) {
            tip->to_fn = func;
            tip->to_arg = arg;
            tip->to_wait.tv_sec = when->tv_sec - now.tv_sec;
            if (when->tv_nsec >= now.tv_nsec) {
                tip->to_wait.tv_nsec = when->tv_nsec - now.tv_nsec;
            } else {
                tip->to_wait.tv_sec--;
                tip->to_wait.tv_nsec = SECTONSEC - now.tv_nsec +
                  when->tv_nsec;

           }
           err = makethread(timeout_helper, (void *)tip);
           if (err == 0)
               return;
        }
    }

    /*
     * We get here if (a) when <= now, or (b) malloc fails, or
     * (c) we can't make a thread, so we just call the function now.
     */
    (*func)(arg);
}

pthread_mutexattr_t attr;
pthread_mutex_t mutex;

void
retry(void *arg)
{
    pthread_mutex_lock(&mutex);
    /* perform retry steps ... */
    pthread_mutex_unlock(&mutex);
}

int
main(void)
{
    int             err, condition, arg;
    struct timespec when;

    if ((err = pthread_mutexattr_init(&attr)) != 0)
        err_exit(err, "pthread_mutexattr_init failed");
    if ((err = pthread_mutexattr_settype(&attr,
      PTHREAD_MUTEX_RECURSIVE)) != 0)
        err_exit(err, "can't set recursive type");
    if ((err = pthread_mutex_init(&mutex, &attr)) != 0)
        err_exit(err, "can't create recursive mutex");
    /* ... */
    pthread_mutex_lock(&mutex);
    /* ... */
    if (condition) {
        /* calculate target time "when" */
        timeout(&when, retry, (void *)arg);
    }
    /* ... */
    pthread_mutex_unlock(&mutex);
    /* ... */
    exit(0);
}


2)读写锁属性

 

#include <pthread.h>

int pthread_rwlockattr_init(pthread_rwlockattr_t
 *attr);

int pthread_rwlockattr_destroy
(pthread_rwlockattr_t *attr);

 

Both return: 0 if OK, error number on failure

 

#include <pthread.h>

int pthread_rwlockattr_getpshared(const
 pthread_rwlockattr_t *
                                  restrict attr,
                                  int *restrict
pshared);

int pthread_rwlockattr_setpshared
(pthread_rwlockattr_t *attr,
                                  int pshared);

 

Both return: 0 if OK, error number on failure

3)条件变量属性

 

#include <pthread.h>

int pthread_condattr_init(pthread_condattr_t *attr);

int pthread_condattr_destroy(pthread_condattr_t
 *attr);

 

Both return: 0 if OK, error number on failure

 

#include <pthread.h>

int pthread_condattr_getpshared(const
 pthread_condattr_t *
                                restrict attr,
                                int *restrict
pshared);

int pthread_condattr_setpshared(pthread_condattr_t
 *attr,
                                int pshared);

 

Both return: 0 if OK, error number on failure


4.重入

一个函数在同一时刻可以被多个线程安全地调用,就称改函数是线程安全的。

5.线程私有数据

 

 

#include <pthread.h>

int pthread_key_create(pthread_key_t *keyp,
                       void (*destructor)(void *));

 

Returns: 0 if OK, error number on failure

 

 

#include <pthread.h>

int pthread_key_delete(pthread_key_t *key);

 

Returns: 0 if OK, error number on failure

 

#include <pthread.h>

pthread_once_t initflag = PTHREAD_ONCE_INIT;

int pthread_once(pthread_once_t *initflag, void 
(*initfn)(void));

 

Returns: 0 if OK, error number on failure


键和线程私有数据的关联

 

 

#include <pthread.h>

void *pthread_getspecific(pthread_key_t key);

 

Returns: thread-specific data value or NULL if no value
has been associated with the key

int pthread_setspecific(pthread_key_t key, const
 void *value);

 

Returns: 0 if OK, error number on failure


6.取消选项

线程的可取消状态和可取消类型。这两个属性直接影响到pthread_cancel函数调用是呈现的行为

 

 

#include <pthread.h>

int pthread_setcancelstate(int state, int *oldstate);

 

Returns: 0 if OK, error number on failure

 

自己添加取消点

 

 

#include <pthread.h>

void pthread_testcancel(void);

 


修改取消类型

 

 

#include <pthread.h>

int pthread_setcanceltype(int type, int *oldtype);

 

Returns: 0 if OK, error number on failure


7. 线程和信号

 

#include <signal.h>

int pthread_sigmask(int how, const sigset_t
 *restrict set,
                    sigset_t *restrict oset);

 

Returns: 0 if OK, error number on failure

 

#include <signal.h>

int sigwait(const sigset_t *restrict set, int
 *restrict signop);

 

Returns: 0 if OK, error number on failure

 

 

#include <signal.h>

int pthread_kill(pthread_t thread, int signo);

 

Returns: 0 if OK, error number on failure


例:同步信号处理

#include "apue.h"
#include <pthread.h>

int         quitflag;   /* set nonzero by thread */
sigset_t    mask;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t wait = PTHREAD_COND_INITIALIZER;

void *
thr_fn(void *arg)
{
    int err, signo;

    for (;;) {
        err = sigwait(&mask, &signo);
        if (err != 0)
            err_exit(err, "sigwait failed");
        switch (signo) {
        case SIGINT:
            printf("\ninterrupt\n");
            break;

        case SIGQUIT:
            pthread_mutex_lock(&lock);
            quitflag = 1;
            pthread_mutex_unlock(&lock);
            pthread_cond_signal(&wait);
            return(0);

        default:
            printf("unexpected signal %d\n", signo);
            exit(1);
        }
    }
}
int
main(void)
{
    int         err;
    sigset_t    oldmask;
    pthread_t   tid;

    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGQUIT);
    if ((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0)
        err_exit(err, "SIG_BLOCK error");

    err = pthread_create(&tid, NULL, thr_fn, 0);
    if (err != 0)
        err_exit(err, "can't create thread");

    pthread_mutex_lock(&lock);
    while (quitflag == 0)
        pthread_cond_wait(&wait, &lock);
    pthread_mutex_unlock(&lock);

    /* SIGQUIT has been caught and is now blocked; do whatever */
    quitflag = 0;

    /* reset signal mask which unblocks SIGQUIT */
    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        err_sys("SIG_SETMASK error");
    exit(0);
}


 

8.线程和fork

 

在子进程内部只存在一个线程,它是由父进程中调用fork的线程的副本构成

如果父进程包含多个线程,子进程在fork返回后,如果接着不是马上调用exec的话,就需要清理锁状态


 

 

#include <pthread.h>

int pthread_atfork(void (*prepare)(void), void 
(*parent)(void),
                   void (*child)(void));

 

Returns: 0 if OK, error number on failure


例:

#include "apue.h"
#include <pthread.h>

pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;

void
prepare(void)
{
    printf("preparing locks...\n");
    pthread_mutex_lock(&lock1);
    pthread_mutex_lock(&lock2);
}
void
parent(void)
{
    printf("parent unlocking locks...\n");
    pthread_mutex_unlock(&lock1);
    pthread_mutex_unlock(&lock2);
}

void
child(void)
{
    printf("child unlocking locks...\n");
    pthread_mutex_unlock(&lock1);
    pthread_mutex_unlock(&lock2);
}

void *
thr_fn(void *arg)
{
    printf("thread started...\n");
    pause();
    return(0);
}

int
main(void)
{
    int         err;
    pid_t       pid;
    pthread_t   tid;

#if defined(BSD) || defined(MACOS)
    printf("pthread_atfork is unsupported\n");
#else
    if ((err = pthread_atfork(prepare, parent, child)) != 0)
        err_exit(err, "can't install fork handlers");
    err = pthread_create(&tid, NULL, thr_fn, 0);
    if (err != 0)
        err_exit(err, "can't create thread");
    sleep(2);
    printf("parent about to fork...\n");
    if ((pid = fork()) < 0)
        err_quit("fork failed");
    else if (pid == 0) /* child */
        printf("child returned from fork\n");
    else        /* parent */
        printf("parent returned from fork\n");
#endif
    exit(0);
}

 9.线程和IO

pread pwrite在多线程环境中非常有帮助

分享到:
评论

相关推荐

    Unix-Linux-Windows-OpenMP多线程编程.docx

    Unix-Linux-Windows-OpenMP 多线程编程知识点总结 POSIX 的基本知识 POSIX(Portable Operating System Interface)是一种可移植操作系统接口标准,旨在提供源代码级的软件可移植性。POSIX 标准定义了操作系统应该...

    UNIX编程艺术 - 扫描版 - 书签

    根据提供的信息,我们可以了解到这是一本关于《UNIX编程艺术》的经典书籍,该书提供了高清扫描版本,并且包含完整的书签,方便读者进行阅读与查阅。接下来,我们将从这本书的主题出发,探讨几个重要的UNIX编程概念与...

    Unix-Linux-Windows-OpenMP多线程编程.pdf

    Unix-Linux-Windows-OpenMP 多线程编程 本文档主要介绍 Unix/Linux 多线程编程接口及编程技术,重点讲解 POSIX 的一些基本知识。POSIX 是可移植操作系统接口(Portable Operating System Interface)的首字母缩写,...

    linux编程技术-多线程-网络编程

    本资料集专注于"Linux编程技术-多线程-网络编程",它涵盖了UNIX环境高级编程、Linux网络编程、Linux多线程编程、Linux窗口编程以及Linux脚本编程等多个核心主题。这些内容都是构建高效、可靠且可扩展的Linux应用的...

    UNIX高级编程5-6(大师著作)

    通过学习《UNIX高级编程》,程序员不仅可以掌握UNIX编程的核心技术,还能培养出系统级别的思维,从而能够设计和编写更高效、更稳定、更健壮的软件系统。无论是对初学者还是经验丰富的开发者,这都是一本极具价值的...

    UNIX----系统编程

    - **POSIX标准**:提供了跨平台的UNIX编程接口,如pthread库用于线程编程。 通过深入学习和实践以上知识点,你将能够熟练地进行UNIX系统编程,开发出高效、稳定的应用程序。记得结合《UNIX系统编程》这样的参考...

    UNIX环境高级编程-pdf

    《UNIX环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,主要针对那些希望深入理解UNIX操作系统,并能熟练进行...无论是自学还是作为参考手册,这本书及其相关资料都能为你的UNIX编程之路提供强大的支持。

    unix网络编程--第一卷----套接口API

    《UNIX网络编程——第一卷——套接口API》是网络编程领域的经典之作,尤其在UNIX操作系统环境下,这本书被视为不可或缺的学习资源。作者深入浅出地讲解了网络通信的基础理论和实际操作,帮助开发者理解如何利用套...

    UNIX网络编程-第2卷-进程间通讯

    《UNIX网络编程-第2卷-进程间通讯》是一本深入探讨UNIX系统中进程间通信(Inter-Process Communication, IPC)的经典著作。该书详细阐述了如何在多进程环境中实现有效的数据交换,这对于理解操作系统原理、开发高效...

    Unix编程艺术/Unix环境高级编程(第二版)/Unix网络编程(第二版)

    《Unix编程艺术》、《Unix环境高级编程(第二版)》和《Unix网络编程(第二版)》是三本在IT领域中具有深远影响力的经典著作,涵盖了Unix操作系统的核心概念、系统调用、进程管理、文件操作、网络通信等多个重要主题...

    UNIX高级编程18-20(大师著作)

    UNIX系统以其稳定、高效和强大的命令行接口而著名,对于系统管理员和高级程序员来说,深入理解和掌握UNIX的高级编程技巧至关重要。"UNIX高级编程18-20(大师著作)"这部分内容可能涵盖了以下几个关键知识点: 1. **...

    Linux/UNIX网络编程》-甘刚-电子教案

    《Linux/UNIX网络编程》是甘刚教授撰写的一本深入探讨网络编程技术的专业书籍,主要针对使用Linux和UNIX操作系统进行网络应用开发的程序员。这本书详细介绍了如何在这些系统上构建网络应用程序,涵盖了从基础概念到...

    UNIX环境高级编程 -- PDF格式

    《UNIX环境高级编程》是一本深受程序员喜爱的经典教程,它深入介绍了在UNIX操作系统环境下进行系统级编程的各种技术和方法。这本书不仅适用于C++开发者,也对任何想要深入理解UNIX系统的程序员都极具价值。以下是对...

    QNX-UNIX-POSIX-C函数手册-chm格式.7z

    在 UNIX 和 POSIX 环境中,C函数不仅包含C语言的标准库,还包含了一组扩展函数,这些函数允许程序员直接与操作系统进行交互,如文件系统操作、进程控制、信号处理、网络通信等。例如,`fork()`函数用于创建新的进程...

    Unix编程艺术中文版(非加密,带目录)

    掌握进程的创建、调度和控制机制是Unix编程的基础。 2. **信号处理**:信号是在Unix系统中用于通知进程发生某些事件的一种机制。学会如何处理这些信号有助于编写更健壮的程序。 3. **I/O操作**:输入输出操作是...

    UNIX环境高级编程--原始代码

    10. **POSIX线程(pthread)编程**:介绍多线程的概念,线程创建(pthread_create())、同步(pthread_mutex_t, pthread_cond_t等)和线程属性设置。 通过实践这些示例代码,开发者不仅可以了解UNIX系统的底层工作...

    HP-UNIX.rar_hp_hp unix_hp-unix download

    1. **多线程和多进程支持**:HP-UNIX支持多线程和多进程并发执行,使得系统能够高效地处理多个任务,提升整体工作效率。 2. **高级内存管理**:具备先进的内存分配和回收机制,确保系统的稳定运行,减少因内存泄露...

    多线程编程UNIXLinux下的多线程编程.pdf

    ### 多线程编程在UNIX/Linux环境中的应用与优势 多线程编程作为一种高效的数据处理方式,在...然而,多线程编程也带来了线程安全、同步控制等挑战,开发者需谨慎处理共享资源的访问,避免出现竞态条件和死锁等问题。

Global site tag (gtag.js) - Google Analytics