一、pthread 线程
    
 
优点:
比多进程节省资源,可以共享变量。
概念:
线程是轻量级进程,一般是一个进程中的多个任务。
进程是系统中最小的资源分配单位.
线程是系统中最小的执行单位
特征:
1、共享资源
 2、效率高  30%
 3、三方库: pthread  clone   posix
      3.1 编写代码头文件: pthread.h
      3.2 编译代码加载库: -lpthread   library 
             libpthread.so //库文件命名
             gcc 1.c -lpthread //编入库
缺点:
1、线程和进程相比,稳定性,稍微差些
 2、线程的调试gdb,相对麻烦些。
                               info thread 
                                        *1  
                                          2 
                                          3
                               thread 3 
         
线程与进程区别:
 1、资源:
         线程比进程多了共享资源。  IPC
         线程(8M)又具有部分私有资源(各自的栈)。
         进程(3G)间只有私有资源没有共享资源。
   2、 空间:
         进程空间独立,不能直接通信。
         线程可以共享空间,可以直接通信
   3、进程---复杂问题
        线程---简单问题
   4、线程属于某个进程
线程与进程共同处:
1、并发
二、线程的设计框架 posix
创建多线程 ==》线程空间操作 ===》线程资源回收
 errno   strerror(errno)  perror();
1、创建多线程
2.1.1 pthread_create
     int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                                  void *(*start_routine) (void *), void *arg);
     功能:该函数可以创建指定的一个线程。
     参数:thread 线程id,需要实现定义并由该函数返回。
                attr   线程属性,一般是NULL,表示默认属性。
                start_routine 指向指针函数的函数指针。
                   本质上是一个函数的名称即可。称为
 th                回调函数,是线程的执行空间。
 {
 }
           arg  回调函数的参数,即参数3的指针函数参数。
     返回值:成功 0
                   失败 非0错误码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
void *th1 (void*arg)
{while(1){printf("发送视频\n");sleep(1);}
}void *th2 (void*arg)
{while(1){printf("接受控制\n");sleep(1);}
}int main(int argc, char *argv[])
{pthread_t tid1,tid2;pthread_create(&tid1,NULL,th1,NULL);pthread_create(&tid1,NULL,th2,NULL);while(1);return 0;
}
2.1.2 注意:
一次pthread_create 执行只能创建 一个线程。
每个进程 至少有一个线程 称为 主线程。
主线程退出 则 所有创建的子线程都退出。 
主线程 必须有 子线程同时运行 才算 多线程程序。
线程id 是线程的 唯一标识,是CPU维护的一组数字。
pstree 查看系统中 多线程的对应关系。
多个子线程 可以 执行同一回调函数。
ps -eLf 查看线程相关信息 Low Weigth Process
 ps -eLo pid,ppid,lwp,stat,comm 
2.1.3 pthread_self
pthread_t pthread_self(void); unsigned long int;  %lu (printf("%lu",pthread_self());)
    功能:获取当前线程的线程id
    参数:无
    返回值:成功 返回当前线程的线程id
                  失败  -1;
             syscall(SYS_gettid);
 这个方法重启后失效
 alias gcc='gcc -g -pthread '
 unalias gcc 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
void *th1 (void*arg)
{while(1){printf("发送视频 %lu\n",pthread_self());sleep(1);}
}void *th2 (void*arg)
{while(1){printf("接受控制 %lu\n",pthread_self());sleep(1);}
}int main(int argc, char *argv[])
{pthread_t tid1,tid2;pthread_create(&tid1,NULL,th1,NULL);pthread_create(&tid2,NULL,th2,NULL);printf("main th %lu\n",pthread_self());while(1);return 0;
}
2、线程的退出
2.2.1 pthread_exit
        自行退出 ==》自杀  ==》子线程自己退出
         exit(1);
         void pthread_exit(void *retval);  exit  return p;
         功能:子线程自行退出
         参数: retval 线程退出时候的返回状态,临死遗言。
         返回值:无
            th
             {
                 int a =10;
                pthread_exit(&a);
             }
             join(,&ret)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
void *th1 (void*arg)
{int i =3;while(i--){printf("发送视频 %lu\n",pthread_self());sleep(1);}pthread_exit(NULL);//return NULL;
}void *th2 (void*arg)
{int i = 3;while(i--){printf("接受控制 %lu\n",pthread_self());sleep(1);}pthread_exit(NULL);
}int main(int argc, char *argv[])
{pthread_t tid1,tid2;pthread_create(&tid1,NULL,th1,NULL);pthread_create(&tid2,NULL,th2,NULL);printf("main th %lu\n",pthread_self());while(1);return 0;
}

2.2.2 pthread_cancel
        强制退出 ==》他杀  ==》主线程结束子线程
         int pthread_cancel(pthread_t thread);
         功能:请求结束一个线程
         参数:thread 请求结束一个线程tid
         返回值:成功 0
                       失败 非0错误号; 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
void *th1 (void*arg)
{while(1){printf("发送视频\n");sleep(1);}
}void *th2 (void*arg)
{while(1){printf("接受控制\n");sleep(1);}
}int main(int argc, char *argv[])
{pthread_t tid1,tid2;pthread_create(&tid1,NULL,th1,NULL);pthread_create(&tid2,NULL,th2,NULL);int i = 0 ;while(1){i++;if(3 == i ){pthread_cancel(tid1);}if(5 ==i){pthread_cancel(tid2);}sleep(1);}return 0;
}
(时间可能不准确,大致3s关,5s关,线程同时走)每次结果可能都不一样

3、线程的回收
2.3.1 线程的回收机制
====》不同与进程没有孤儿线程和僵尸线程。
 ====》主线程结束任意生成的子线程都会结束。
 ====》子线程的结束不会影响主线程的运行。
     char * retval ; retval++; 1 
     int * retval; 
2.3.2 pthread_join
   int pthread_join(pthread_t thread, void **retval);    
   功能:通过该函数可以将指定的线程资源回收,该函数具有阻塞等待功能,如果指定的线程没有               结束,则回收线程会阻塞。(如果子线程没有回收成功,主线程不会执行后面的代码)
   参数:thread  要回收的子线程tid
              retval  要回收的子线程返回值/状态。==》ptread_exit(值);
   返回值:成功 0
                 失败 非0错误号;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
void *th1 (void*arg)
{int i = 3;while(i--){printf("发送视频\n");sleep(1);}
}void *th2 (void*arg)
{int i = 3;while(i--){printf("接受控制\n");sleep(1);}
}int main(int argc, char *argv[])
{pthread_t tid1,tid2;pthread_create(&tid1,NULL,th1,NULL);pthread_join(tid1,NULL);pthread_join(tid2,NULL);printf("子线程已被回收\n");return 0;
}
join接收返回值
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>void* th(void* arg)
{static char buf[256]={0};strcpy(buf,"要消亡了\n");return buf;
}int main(int argc, char *argv[])
{pthread_t tid;void* ret;pthread_create(&tid,NULL,th,NULL);pthread_join(tid,&ret);printf("ret %s\n",(char*)ret);return 0;
} 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>void* th(void* arg)
{static int a =20;return &a;
}int main(int argc, char *argv[])
{pthread_t tid;void* ret;pthread_create(&tid,NULL,th,NULL);pthread_join(tid,&ret);printf("ret %d\n",*(int*)ret);return 0;
}
2.3.3 子线程的回收策略
  1)如果预估 子线程可以有限范围内结束 则 正常用pthread_join等待回收。
   2)如果预估 子线程可能休眠 或者 阻塞 则 等待一定时间后 强制回收。
   3)如果子线程已知 必须长时间运行 则 不再回收其资源。 
4、线程的参数,返回值
5、线程的清理(成对使用)
2.5.1 cleanup_push
void pthread_cleanup_push(void (*routine)(void *),void *arg);//相当于do while 中的 do
    功能:注册一个线程清理函数
     参数:routine,线程清理函数的入口
                arg,清理函数的参数
     返回值:无
2.5.2 cleanup_pop
void pthread_cleanup_pop(int execute);//相当于do while 中的 while
     功能:调用清理函数
     参数: execute,非0  执行清理函数
                                    0  不执行清理   
     返回值:无
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>void clean(void* arg)
{printf("this is clean ,arg is %s\n",(char*)arg);free(arg);
}
void* th(void*arg)
{pthread_cleanup_push(clean,arg);printf("th arg is %s\n",(char*)arg);pthread_cleanup_pop(1);return NULL;
}int main(int argc, char *argv[])
{pthread_t tid;char* p = (char*)malloc(50);strcpy(p,"hello");pthread_create(&tid,NULL,th,p);pthread_join(tid,NULL);return 0;
}