进程原语 线程原语 描述
fork pthread_create 创建新的控制流
exit pthread_exit 从现有的控制流中退出
waitpid pthread_join 从控制流中得到退出状态
atexit pthread_cancel_push 注册在退出控制流时调用的函数
getpid pthread_self 获取控制流的ID
abort pthread_cancel 请深圳市控制流的非正常退出

pthread_create

int pthread_create(pthread_t *thread, pthread_addr_t *arr,void* (*start_routine)(void *), void *arg);

  • thread    :用于返回创建的线程的ID
  • arr         : 用于指定的被创建的线程的属性,上面的函数中使用NULL,表示使用默认的属性
  • start_routine      : 这是一个函数指针,指向线程被创建后要调用的函数
  • arg        : 用于给线程传递参数,在本例中没有传递参数,所以使用了NULL
 
线程创建时并不能保证哪个线程会先运行:是新创建的线程还是调用线程。新创建的线程可以访问进程的地址空间,
并且继承调用线程的浮点环境和信号屏蔽字,但是该线程的未决信号集被消除。
 
单个线程可以通过三种方式退出,在不终止整个进程的情况下停止它的控制流。
(1)线程只是从启动全程中返回,返回值是线程的退出码。
(2)线程可以被同一进程中的其他线程取消
(3)线程调用pthread_exit
 
 
void pthread_exit(void *rval_ptr)
rval_ptr是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。
 
int pthread_join(pthread_t thread,void **rval_ptr);
成功返回0,失败返回错误编号
调用线程将一直阻塞,直到指定的线程调用pthread_exit,从启动例程中返回或者被取消。
如果线程只是从它的启动例程返回,rval_ptr将包含返回码。如果线程被取消,由rval_ptr指定的内存单元被置为PTHREAH_CANCELED.
可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL.
如果对线程的返回值并不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程停止,但并不获取线程的终止状态。
 
在 调用线程的栈上分配了该结构,那么其他的线程在使用这个结构进内存可能已经改变了。又如,线程在自己的栈上分配了一个结构然后把指向这个结构的指针传给 pthread_exit,那么当调用pthread_join的线程试图使用该结构时,这个栈有可能已经被撤消,这块内存也已另作他用。
例如:#include <stdlib.h>
 
void pthread_cleanup_push(void (*rtn)(void *),void *arg);
void pthread_cleanup_pop(int execute);
当线程执行以下动作时调用清理函数,调用参数为arg,清理函数rtn的调用顺序是由pthread_cleanup_push函数来安排的。
1.调用pthread_exit时。2.响应取消请求时。3.用非零execute参数调用pthread_cleanup_pop时。
如果execute参数置为0,清理函数将不被调用。无论哪种情况,pthread_cleanup_pop都将删除上次pthread_clean_push调用建立的清理处理程序。
实例:
 #include <stdlib.h>
#include <stdio.h>
#include <pthread.h> void cleanup(void *arg)
{
printf("cleanup: %s\n", (char *)arg);
} void *thr_fn1(void *arg)
{
printf("thread 1 start\n");
pthread_cleanup_push(cleanup, "thread 1 first handler");
pthread_cleanup_push(cleanup, "thread 1 second handler");
printf("thread 1 push complete\n");
if (arg)
return((void *));
// pthread_exit((void *)2); pthread_cleanup_pop();
pthread_cleanup_pop();
// return((void *)1);
pthread_exit((void *)); } void *thr_fn2(void *arg)
{
printf("thread 2 start\n");
pthread_cleanup_push(cleanup, "thread 2 first handler");
pthread_cleanup_push(cleanup, "thread 2 second handler");
printf("thread 2 push complete\n");
if (arg)
pthread_exit((void *));
pthread_cleanup_pop();
pthread_cleanup_pop();
pthread_exit((void *));
} int main(void)
{
int err;
pthread_t tid1, tid2;
void *tret; err = pthread_create(&tid1, NULL, thr_fn1, (void *));
if (err != )
printf("can't create thread 1: %c\n", strerror(err));
err = pthread_create(&tid2, NULL, thr_fn2, (void *));
if (err != )
printf("can't create thread 2: %c\n", strerror(err));
err = pthread_join(tid1, &tret);
if (err != )
printf("can't join with thread 1: %c\n", strerror(err));
printf("thread 1 exit code %d\n", (int)tret);
err = pthread_join(tid2, &tret);
if (err != )
printf("can't join with thread 2: %c\n", strerror(err));
printf("thread 2 exit code %d\n", (int)tret);
exit();
}

linux c学习笔记----线程创建与终止的更多相关文章

  1. linux c学习笔记----进程创建(fork,wait,waitpid)

    1.pid_t fork(); (1)当一个进程调用了fork 以后,系统会创建一个子进程.这个子进程和父进程不同的地方只有他的进程ID 和父进程ID,其他的都是一样.就象符进程克隆(clone)自己 ...

  2. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  3. Java基础学习总结(88)——线程创建与终止、互斥、通信、本地变量

    线程创建与终止 线程创建 Thread类与 Runnable 接口的关系 public interface Runnable {         public abstract void run(); ...

  4. Linux系统学习笔记:文件I/O

    Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...

  5. Linux内核学习笔记-2.进程管理

    原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  6. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

  7. 尚硅谷韩顺平Linux教程学习笔记

    目录 尚硅谷韩顺平Linux教程学习笔记 写在前面 虚拟机 Linux目录结构 远程登录Linux系统 vi和vim编辑器 关机.重启和用户登录注销 用户管理 实用指令 组管理和权限管理 定时任务调度 ...

  8. Linux内核学习笔记-1.简介和入门

    原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  9. linux kernel学习笔记-5内存管理_转

    void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...

随机推荐

  1. 个基于TensorFlow的简单故事生成案例:带你了解LSTM

    https://medium.com/towards-data-science/lstm-by-example-using-tensorflow-feb0c1968537 在深度学习中,循环神经网络( ...

  2. 强制开启android webview debug模式使用Chrome inspect

    强制开启android webview debug模式使用Chrome inspect https://blog.csdn.net/zhulin2609/article/details/5143782 ...

  3. 如何拷贝一个wchar_t类型的字符串

    Do this, wchar_t clone[260]; wcscpy(clone,szPath); Or, if you want to allocate memory yourself, wcha ...

  4. ASP入门(四)-VBScript的流程控制语句

    VBScript条件语句 我们可以使用四种条件语句 If - Then - 语句 If - Then - Else 语句 If - Then - ElseIf 语句 Select - Case 语句 ...

  5. oracle SGA

    3.2 SGA系统全局区--System global area(SGA) 是一组共享的内存结构,它里面存储了oracle数据库实例(instance)的数据和控制文件信息.如果有多个用户同时连接到数 ...

  6. Mybatis 自定义SqlSessionFactoryBean扫描通配符typeAliasesPackage

    typeAliasesPackage 默认只能扫描某一个路径下,或以逗号等分割的 几个路径下的内容,不支持通配符和正则,采用重写的方式解决 package com.xxxx.xxx.util.comm ...

  7. iOS 中基础字符判断函数收集(如判断大小写、数字等)

    函数:isdigit 用法:#include 功能:判断字符c是否为数字 说明:当c为数字0-9时,返回非零值,否则返回零. 函数:islower 用法:#include 功能:判断字符c是否为小写英 ...

  8. 线程:主线程、子线程 同步线程、异步线程 单线程、多线程 System.Threading与System.Windows.Threading

    入门-------------------------------------------------------------------------------- 概述与概念    一个C#程序开始 ...

  9. jquery.cookie.js结合asp.net实现最近浏览记录

    一.html代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  10. Kettle命令行使用说明

    Kettle命令行使用说明 1.Pan——转换执行器 用来执行转换.参数与Kitchen类似,如下. 1- -version显示版本信息 2- -file=filename运行xml文件 3- -pa ...