================ 第九课 线程管理 ================ 一、基本概念 ------------ 1. 线程就是程序的执行路线,即进程内部的控制序列, 或者说是进程的子任务。 2. 线程,轻量级,不拥有自己独立的内存资源, 共享进程的代码区、数据区、堆区(注意没有栈区, 线程拥有自己独立的栈)、 环境变量和命令行参数、文件描述符、信号处理函数、 当前目录、用户ID和组ID等资源。 3. 线程拥有自己独立的栈,因此也有自己独立的局部变量。 4. 一个进程可以同时拥有多个线程, 即同时被系统调度的多条执行路线, 但至少要有一个主线程。 二、基本特点 ------------ 1. 线程是进程的一个实体, 可作为系统独立调度和分派的基本单位。 (p.s. 进程是一堆数据资源,没有所谓调度,调度是针对动作的,对于动作是否要进行我们需要调度) 2. 线程有不同的状态,系统提供了多种线程控制原语(所谓原语就是进行多线程控制的函数), 如创建线程、销毁线程等等。 3. 线程不拥有自己的资源(线程所独立拥有的栈只是为了执行动作需要的临时场地,不算资源, 因为临时场地不可持续), 只拥有从属于进程的全部资源, 所有的资源分配都是面向进程的。 4. 一个进程中可以有多个线程并发地运行。 它们可以执行相同的代码,也可以执行不同的代码。 5. 同一个进程的多个线程都在同一个地址空间内活动, 因此相对于进程,线程的系统开销小,任务切换快。 6. 线程间的数据交换不需要依赖于类似IPC的特殊通信机制, 简单而高效。 7. 每个线程拥有自己独立的线程ID、寄存器信息、函数栈、 错误码和信号掩码。 8. 线程之间存在优先级的差异。 三、POSIX线程(pthread) ---------------------- 1. 早期厂商各自提供私有的线程库版本, 接口和实现的差异非常大,不易于移植。 2. IEEE POSIX 1003.1c (1995)标准, 定义了统一的线程编程接口, 遵循该标准的线程实现被统称为POSIX线程,即pthread。 3. pthread包含一个头文件pthread.h, 和一个接口库libpthread.so。 #include <pthread.h> ... gcc ... -lpthread 4. 功能 1) 线程管理:创建/销毁线程、分离/联合线程、 设置/查询线程属性。 2) 线程同步 A. 互斥量:创建/销毁互斥量、加锁/解锁互斥量、 设置/查询互斥量属性。 B. 条件变量:创建/销毁条件变量、等待/触发条件变量、 设置/查询条件变量属性。 四、线程函数 ------------ 1. 创建线程 ~~~~~~~~~~~ int pthread_create (pthread_t* restrict thread, //thread - 线程ID,输出参数。 //pthread_t在某些厂商的实现上即unsigned long int。 const pthread_attr_t* restrict attr, //attr - 线程属性,NULL表示缺省属性。 //pthread_attr_t可能是整型也可能是结构, //因实现而异。 void* (*start_routine) (void*), //start_routine - 线程过程函数指针, //参数和返回值的类型都是void*。 //启动线程本质上就是调用一个函数, //只不过是在一个独立的线程中调用的, //函数返回即线程结束。 void* restrict arg //arg - 传递给线程过程函数的参数。 //线程过程函数的调用者是系统内核, //而非用户代码, //因此需要在创建线程时指定参数。 ); 成功返回0,失败返回错误码。 注意: 1) restrict: C99引入的编译优化指示符, 提高重复解引用同一个指针的效率。 2) 在pthread.h头文件中声明的函数, 通常以直接返回错误码的方式表示失败, 而非以错误码设置errno并返回-1来指示成功与失败。 3) main函数即主线程, 程序一运行内核就会启动一个线程,这个线程的开始就执行main函数,这个线程称为主线程,main函数返回即主线程结束, 主线程结束即进程结束, 进程一但结束其所有的线程即结束。 4) 应设法保证在线程过程函数执行期间, 其参数所指向的目标持久有效。 创建线程。范例:create.c/* * 文件名:create.c * */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> void* thread_proc (void* arg) { printf ("%lu线程:%s\n", pthread_self (), (char*)arg); return NULL; } int main (void) { setbuf(stdout, NULL); pthread_t tid; int error = pthread_create (&tid, NULL, thread_proc, "我是快乐的子线程!"); if (error) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } printf ("%lu线程:我是主线程,创建了%lu线程。\n", pthread_self (), tid); sleep (1); return 0; }
线程并发。范例:concur.c/* * 文件名: concur.c * */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> void* thread_proc (void* arg) { size_t i; for (i = 0; i < 500; i++) { printf ("%*c\n", ((size_t)arg + 1) * 1, 'A' + (i + 1) % 10); usleep (50000); } return NULL; } int main (void) { pthread_t tids[50]; size_t i; for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++) { int error = pthread_create (&tids[i], NULL, thread_proc, (void*)i); if (error) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } } for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++) { int error = pthread_join (tids[i], NULL); if (error) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } } return 0; }
线程参数。范例:arg.c/* * 文件名: arg.c * * 多线程练习 * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <unistd.h> #include <pthread.h> #define PAI 3.14159 void* thread_area (void* arg) { double r = *(double*)arg; *(double*)arg = PAI * r * r; return NULL; } typedef struct tag_Pyth { double a; double b; double c; } PYTH, *LPPYTH; void* thread_pyth (void* arg) { LPPYTH pyth = (LPPYTH)arg; pyth -> c = sqrt (pyth -> a * pyth -> a + pyth -> b * pyth -> b); return NULL; } void* thread_aver (void* arg) { double* d = (double*)arg; d[2] = (d[0] + d[1]) / 2; return NULL; } void* thread_show (void* arg) { sleep (1); printf ("n = %d\n", *(int*)arg); return NULL; } int main (void) { printf ("r = "); double rs; scanf ("%lf", &rs); pthread_t tid; int error = pthread_create (&tid, NULL, thread_area, &rs); if (error) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } if ((error = pthread_join (tid, NULL)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } printf ("s = %g\n", rs); PYTH pyth; printf ("a = "); scanf ("%lf", &pyth.a); printf ("b = "); scanf ("%lf", &pyth.b); if ((error = pthread_create (&tid, NULL, thread_pyth, &pyth)) != 0) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } if ((error = pthread_join (tid, NULL)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } printf ("c = %g\n", pyth.c); double d[3]; printf ("x = "); scanf ("%lf", &d[0]); printf ("y = "); scanf ("%lf", &d[1]); if ((error = pthread_create (&tid, NULL, thread_aver, d)) != 0) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } if ((error = pthread_join (tid, NULL)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } printf ("z = %g\n", d[2]); int* n = malloc (sizeof (int)); *n = 1234; if ((error = pthread_create (&tid, NULL, thread_show, n)) != 0) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } /* free (n); */ if ((error = pthread_join (tid, NULL)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } free (n); return 0; }
2. 等待线程
~~~~~~~~~~~
int pthread_join (pthread_t thread, void** retval);
等待thread参数所标识的线程结束,
成功返回0,失败返回错误码。
范例:ret.c/* * 文件名: ret.c * * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #define PAI 3.14159 void* thread_area (void* arg) { double r = *(double*)arg; /* static double s; s = PAI * r * r; return &s; */ double* s = malloc (sizeof (double)); *s = PAI * r * r; return s; } int main (void) { printf ("r = "); double r; scanf ("%lf", &r); pthread_t tid; int error = pthread_create (&tid, NULL, thread_area, &r); if (error) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } double* s; if ((error = pthread_join (tid, (void**)&s)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } printf ("s = %g\n", *s); free (s); return 0; }
注意从线程过程函数中返回值的方法:
1) 线程过程函数将所需返回的内容放在一块内存中,
返回该内存的地址,需要保证这块内存在函数返回,
即线程结束,以后依然有效;
2) 若retval参数非NULL,
则pthread_join函数将线程过程函数所返回的指针,
拷贝到该参数所指向的内存中;
3) 若线程过程函数所返回的指针指向动态分配的内存,
则还需保证在用过该内存之后释放之。
3. 获取线程自身的ID
~~~~~~~~~~~~~~~~~~~
pthread_t pthread_self (void);
成功返回调用线程的ID,不会失败。
4. 比较两个线程的ID
~~~~~~~~~~~~~~~~~~~
int pthread_equal (pthread_t t1, pthread_t t2);
若参数t1和t2所标识的线程ID相等,则返回非零,否则返回0。
某些实现的pthread_t不是unsigned long int类型,
可能是结构体类型,无法通过“==”判断其相等性。
范例:equal.c/* * pthread_equal()函数练习 * */ #include <stdio.h> #include <string.h> #include <pthread.h> pthread_t g_main; void* ismain (void* arg) { // if (pthread_self () == g_main) //兼容性不好 if (pthread_equal (pthread_self (), g_main)) printf ("我是主线程!\n"); else printf ("我不是主线程!\n"); return NULL; } int main (void) { g_main = pthread_self (); pthread_t tid; int error = pthread_create (&tid, NULL, ismain, NULL); if (error) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } ismain (NULL); if ((error = pthread_join (tid, NULL)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } return 0; }
5. 终止线程
~~~~~~~~~~~
1) 从线程过程函数中return。
2) 调用pthread_exit函数。
void pthread_exit (void* retval); //等价于return retval;
//也就是说pthread_exit的参数retval - 和线程过程函数的返回值语义相同。
注意:在任何线程中调用exit函数都将终止整个进程。
范例:exit.c/*文件名:exit.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #define PAI 3.14159 void* thread_area (void* arg) { double r = *(double*)arg; double* s = malloc (sizeof (double)); // exit (0); *s = PAI * r * r; pthread_exit (s); // <==> return s; *s = 2 * PAI * r; return s; } int main (void) { printf ("r = "); double r; scanf ("%lf", &r); pthread_t tid; int error = pthread_create (&tid, NULL, thread_area, &r); if (error) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } double* s; if ((error = pthread_join (tid, (void**)&s)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } printf ("s = %g\n", *s); free (s); return 0; }
6. 线程执行轨迹
~~~~~~~~~~~~~~~
1) 同步方式(PTHREAD_CREATE_JOINABLE, 就是非分离状态,或称为可汇合态, 或称为可汇合线程):
创建线程之后调用pthread_join函数等待其终止,
并释放线程资源。
2) 异步方式(PTHREAD_CREATE_DETACHED, 就是分离状态, 或称为分离态, 或称为分离线程):
无需创建者等待,线程终止后自行释放资源。
int pthread_detach (pthread_t thread);
使thread参数所标识的线程进入分离(DETACHED)状态。
处于分离状态的线程终止后自动释放线程资源,
且不能被pthread_join函数等待。
成功返回0,失败返回错误码。
范例:detach.c/* *文件名:detach.c */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> void* thread_proc (void* arg) { int i; for (i = 0; i < 200; i++) { putchar ('-'); usleep (50000); } return NULL; } int main (void) { setbuf (stdout, NULL); pthread_t tid; int error = pthread_create (&tid, NULL, thread_proc, NULL); if (error) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } if ((error = pthread_detach (tid)) != 0) { fprintf (stderr, "pthread_detach: %s\n", strerror (error)); return -1; } /* if ((error = pthread_join (tid, NULL)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } */ int i; for (i = 0; i < 200; i++) { putchar ('+'); usleep (100000); } printf ("\n"); return 0; }
7. 取消线程
~~~~~~~~~~~
1) 向指定线程发送取消请求
int pthread_cancel (pthread_t thread);
成功返回0,失败返回错误码。
注意:该函数只是向线程发出取消请求, 该函数不阻塞,并不等待线程终止。
缺省情况下,线程在收到取消请求以后,并不会立即终止,
而是仍继续运行,直到其达到某个取消点。在取消点处,
线程检查其自身是否已被取消了,并做出相应动作。(p.s. 当线程调用一些特定函数时,取消点会出现。)
2) 设置调用线程的可取消状态
int pthread_setcancelstate (int state, //state取值:
//PTHREAD_CANCEL_ENABLE - 接受取消请求(缺省)。
//PTHREAD_CANCEL_DISABLE - 忽略取消请求。
int* oldstate //可通过oldstate参数(若非NULL)输出原可取消状态
);
成功返回0,失败返回错误码。
3) 设置调用线程的可取消类型
int pthread_setcanceltype (int type, //type取值:
//PTHREAD_CANCEL_DEFERRED - 延迟取消(缺省)。
//被取消线程在接收到取消请求之后并不立即响应,
//而是一直等到执行了特定的函数(取消点)之后再响应该请求。
//
//PTHREAD_CANCEL_ASYNCHRONOUS - 异步取消。
//被取消线程可以在任意时间取消,
//不是非得遇到取消点才能被取消。
//但是操作系统并不能保证这一点。
int* oldtype //可通过oldtype参数(若非NULL)输出原可取消类型
);
成功返回0,失败返回错误码。
范例:cancel.c/* *文件名:cancel.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> void elapse (void) { size_t i; for (i = 0; i < 800000000; ++i); } void* thread_proc (void* arg) { /* int error = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); if (error) { fprintf (stderr, "pthread_setcancelstate: %s\n", strerror (error)); exit (EXIT_FAILURE); } *//* int error = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); if (error) { fprintf (stderr, "pthread_setcanceltype: %s\n", strerror (error)); exit (EXIT_FAILURE); } */ for (;;) { printf ("线程:子在川上曰,逝者如斯夫。\n"); elapse (); } return NULL; } int main (void) { setbuf (stdout, NULL); printf ("按<回车>取消线程...\n"); pthread_t tid; int error = pthread_create (&tid, NULL, thread_proc, NULL); if (error) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } getchar (); if ((error = pthread_cancel (tid)) != 0) { fprintf (stderr, "pthread_cancel: %s\n", strerror (error)); exit (EXIT_FAILURE); } printf ("已发送取消请求,等待线程终止...\n"); if ((error = pthread_join (tid, NULL)) != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (error)); return -1; } printf ("线程已终止。\n"); return 0; }
8. 线程属性
~~~~~~~~~~~
创建线程函数
int pthread_create (pthread_t* restrict thread,
const pthread_attr_t* restrict attr,
void* (*start_routine) (void*),
void* restrict arg);
的第二个参数即为线程属性,传空指针表示使用缺省属性。
typedef struct {
// 分离状态
//
// PTHREAD_CREATE_DETACHED
// - 分离线程。
//
// PTHREAD_CREATE_JOINABLE(缺省)
// - 可汇合线程。
//
int detachstate;
// 竞争范围
//
// PTHREAD_SCOPE_SYSTEM
// - 在系统范围内竞争资源。
//
// PTHREAD_SCOPE_PROCESS(Linux不支持)
// - 在进程范围内竞争资源。
//
int scope;
// 继承特性
//
// PTHREAD_INHERIT_SCHED(缺省)
// - 调度属性自创建者线程继承。
//
// PTHREAD_EXPLICIT_SCHED
// - 调度属性由后面两个成员确定。
//
int inheritsched;
// 调度策略
//
// SCHED_FIFO
// - 先进先出策略。
//
// 没有时间片。
//
// 一个FIFO线程会持续运行,
// 直到阻塞或有高优先级线程就绪。
//
// 当FIFO线程阻塞时,系统将其移出就绪队列,
// 待其恢复时再加到同优先级就绪队列的末尾。
//
// 当FIFO线程被高优先级线程抢占时,
// 它在就绪队列中的位置不变。
// 因此一旦高优先级线程终止或阻塞,
// 被抢占的FIFO线程将会立即继续运行。
//
// SCHED_RR
// - 轮转策略。
//
// 给每个RR线程分配一个时间片,
// 一但RR线程的时间片耗尽,
// 系统即将移到就绪队列的末尾。
//
// SCHED_OTHER(缺省)
// - 普通策略。
//
// 静态优先级为0。任何就绪的FIFO线程或RR线程,
// 都会抢占此类线程。
//
int schedpolicy;
// 调度参数
//
// struct sched_param {
// int sched_priority; /* 静态优先级 */
// };
//
struct sched_param schedparam;
// 栈尾警戒区大小(字节)
//
// 缺省一页(4096字节)。
//
size_t guardsize;
// 栈地址
//
void* stackaddr;
// 栈大小(字节)
//
size_t stacksize;
} pthread_attr_t;
不要手工读写该结构体,
而应调用pthread_attr_set/get函数设置/获取具体属性项。
1) 设置线程属性
第一步,初始化线程属性结构体
int pthread_attr_init (pthread_attr_t* attr);
第二步,设置具体线程属性项
int pthread_attr_setdetachstate (
pthread_attr_t* attr,
int detachstate);
int pthread_attr_setscope (
pthread_attr_t* attr,
int scope);
int pthread_attr_setinheritsched (
pthread_attr_t* attr,
int inheritsched);
int pthread_attr_setschedpolicy (
pthread_attr_t* attr,
int policy);
int pthread_attr_setschedparam (
pthread_attr_t* attr,
const struct sched_param* param);
int pthread_attr_setguardsize (
pthread_attr_t* attr,
size_t guardsize);
int pthread_attr_setstackaddr (
pthread_attr_t* attr,
void* stackaddr);
int pthread_attr_setstacksize (
pthread_attr_t* attr,
size_t stacksize);
int pthread_attr_setstack (
pthread_attr_t* attr,
void* stackaddr, size_t stacksize);
第三步,以设置好的线程属性结构体为参数创建线程
int pthread_create (pthread_t* restrict thread,
const pthread_attr_t* testrict attr,
void* (*start_routine) (void*),
void* restrict arg);
第四步,销毁线程属性结构体
int pthread_attr_destroy (pthread_attr_t* attr);
2) 获取线程属性
第一步,获取线程属性结构体
int pthread_getattr_np (pthread_t thread,
pthread_attr_t* attr);
第二步,获取具体线程属性项
int pthread_attr_getdetachstate (
pthread_attr_t* attr,
int* detachstate);
int pthread_attr_getscope (
pthread_attr_t* attr,
int* scope);
int pthread_attr_getinheritsched (
pthread_attr_t* attr,
int* inheritsched);
int pthread_attr_getschedpolicy (
pthread_attr_t* attr,
int* policy);
int pthread_attr_getschedparam (
pthread_attr_t* attr,
struct sched_param* param);
int pthread_attr_getguardsize (
pthread_attr_t* attr,
size_t* guardsize);
int pthread_attr_getstackaddr (
pthread_attr_t* attr,
void** stackaddr);
int pthread_attr_getstacksize (
pthread_attr_t* attr,
size_t* stacksize);
int pthread_attr_getstack (
pthread_attr_t* attr,
void** stackaddr, size_t* stacksize);
以上所有函数成功返回0,失败返回错误码。
范例:attr.c/* *文件名:attr.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define __USE_GNU #include <pthread.h> int printattrs (pthread_attr_t* attr) { printf("------- 线程属性 -------\n"); int detachstate; int error = pthread_attr_getdetachstate (attr, &detachstate); if (error) { fprintf (stderr, "pthread_attr_getdetachstate: %s\n", strerror (error)); return -1; } printf("分离状态: %s\n", (detachstate == PTHREAD_CREATE_DETACHED) ? "分离线程" : (detachstate == PTHREAD_CREATE_JOINABLE) ? "可汇合线程" : "未知"); int scope; if ((error = pthread_attr_getscope (attr, &scope)) != 0) { fprintf (stderr, "pthread_attr_getscope: %s\n", strerror (error)); return -1; } printf ("竞争范围: %s\n", (scope == PTHREAD_SCOPE_SYSTEM) ? "系统级竞争" : (scope == PTHREAD_SCOPE_PROCESS) ? "进程级竞争" : "未知"); int inheritsched; if ((error = pthread_attr_getinheritsched (attr, &inheritsched)) != 0) { fprintf (stderr, "pthread_attr_getinheritsched: %s\n", strerror (error)); return -1; } printf ("继承特性: %s\n", (inheritsched == PTHREAD_INHERIT_SCHED) ? "继承调用属性" : (inheritsched == PTHREAD_EXPLICIT_SCHED) ? "显式调用属性" : "未知"); int schedpolicy; if ((error = pthread_attr_getschedpolicy(attr, &schedpolicy)) != 0) { fprintf (stderr, "pthread_attr_getschedpolicy: %s\n", strerror (error)); return -1; } printf ("调度策略: %s\n", (schedpolicy == SCHED_OTHER) ? "普通" : (schedpolicy == SCHED_FIFO) ? "先进先出" : (schedpolicy == SCHED_RR) ? "轮转" : "未知"); struct sched_param schedparam; if ((error = pthread_attr_getschedparam (attr, &schedparam)) != 0) { fprintf (stderr, "pthread_attr_getschedparam: %s\n", strerror (error)); return -1; } printf ("调度优先级:%d\n", schedparam.sched_priority); size_t guardsize; if ((error = pthread_attr_getguardsize(attr, &guardsize)) != 0) { fprintf (stderr, "pthread_attr_getguardsize: %s\n", strerror (error)); return -1; } printf ("栈尾警戒区:%u字节\n", guardsize); /* void* stackaddr; if ((error = pthread_attr_getstackaddr (attr, &stackaddr)) != 0) { fprintf (stderr, "pthread_attr_getstackaddr: %s\n", strerror (error)); return -1; } printf ("栈地址: %p\n", stackaddr); size_t stacksize; if ((error = pthread_attr_getstacksize (attr, &stacksize)) != 0) { fprintf (stderr, "pthread_attr_getstacksize: %s\n", strerror (error)); return -1; } printf ("栈大小: %u字节\n", stacksize); */ void* stackaddr; size_t stacksize; if ((error = pthread_attr_getstack (attr, &stackaddr, &stacksize)) != 0) { fprintf (stderr, "pthread_attr_getstack: %s\n", strerror (error)); return -1; } printf ("栈地址: %p\n", stackaddr); printf ("栈大小: %u字节\n", stacksize); printf("------------------------\n"); return 0; } void* thread_proc (void* arg) { pthread_attr_t attr; int error = pthread_getattr_np (pthread_self (), &attr); if (error) { fprintf (stderr, "pthread_getattr_np: %s\n", strerror (error)); exit (EXIT_FAILURE); } if (printattrs (&attr) < 0) exit (EXIT_FAILURE); exit (EXIT_SUCCESS); return NULL; } int main (int argc, char* argv[]) { int error; pthread_attr_t attr, *pattr = NULL; if (argc > 1) { if (strcmp (argv[1], "-s")) { fprintf (stderr, "用法:%s [-s]\n", argv[0]); return -1; } if ((error = pthread_attr_init (&attr)) != 0) { fprintf (stderr, "pthread_attr_init: %s\n", strerror (error)); return -1; } if ((error = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED)) != 0) { fprintf (stderr, "pthread_attr_setdetachstate: %s\n", strerror (error)); return -1; } if ((error = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED)) != 0) { fprintf (stderr, "pthread_attr_setinheritsched: %s\n", strerror (error)); return -1; } if ((error = pthread_attr_setstacksize (&attr, 4096*10)) != 0) { fprintf (stderr, "pthread_attr_setstack: %s\n", strerror (error)); return -1; } pattr = &attr; } pthread_t tid; if ((error = pthread_create (&tid, pattr, thread_proc, NULL)) != 0) { fprintf (stderr, "pthread_create: %s\n", strerror (error)); return -1; } if (pattr) if ((error = pthread_attr_destroy (pattr)) != 0) { fprintf (stderr, "pthread_attr_destroy: %s\n", strerror (error)); return -1; } pause (); return 0; }
Unix C, Day09
最新推荐文章于 2024-08-07 17:41:58 发布