1:从进程引入线程
用多进程(父子进程)分别去执行两个任务(读文件I/O),哈哈这个例子用多进程在于,各自的程序都是阻塞等待一个任务;
代码如下:
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(void)
{
int ret = -1;
int fd = -1;
char buf[100] ={0};
char buf1[100] ={0};
pid_t fpid = -1;
printf("this is parent process\n");
fd = open("/dev/input/mouse0",O_RDONLY);
if(-1==fd)
{
perror("open");
return -1;
}
fpid = fork();
if (-1==fpid)
{
perror("fork");
return -1;
}
if (0==fpid)
{
printf("this is child process\n");
while(1)
{
memset(buf,0,sizeof(buf));
ret=read(fd,buf,7);
if(-1==ret)
{
perror("read");
return -1;
}
printf("子进程读鼠标【%s】\n",buf);
}
}
else if(fpid>0)
{
printf("this is prantent process\n");
while(1)
{
memset(buf1,0,sizeof(buf1));
ret=read(0,buf1,7);
if(-1==ret)
{
perror("read");
return -1;
}
printf("父进程读键盘【%s】\n",buf1);
}
}
else
{
perror("fork");
return -1;
}
return 0;
}
多进程的好处:
- 操作系统可以处理多个任务,也就是其实可以在多个进程之间跳来跳去;
- cpu是分时复用的;
坏处:
- 进程调度开销大;
- 进程间通信巨麻烦;
所以引入线程:
- 节省进程开销;
- 多核cpu越来越是为了满足多线程的功能的;
- 可以实现多任务;
线程详解
相关概念:
- 一种轻量级的进程;
- 线程是参与内核调度的最小单元;线程更加接近于执行体的概念;
- 一个进程当中有多个线程
- 同一个进程中多个线程可以共享数据,但拥有各自的栈空间,独立的执行序列;
线程技术的优势:
- 可以像进程一样被OS调度;
- 进程之间通信效率很容易也很高效;(就好像同一个进程中,不同函数直接的通信)
- 很合适多核心CPU(对称多处理器架构SMP)架构下效率最大化;多线程可以并发在多核当中执行;多进程却不能保证这种并发执行;
缺点:不利于资源的管理和保护;不利于跨机器迁移(???);
线程常用函数
新手教程:新手教程(线程创建,线程属性,线程取消)
一个线程通过一个函数调用产生,产生的thread什么时候死,什么时候(进程被结束的时候死,自己执行完毕,被另一个线程杀死(立刻,还是缓刑))
线程创建与回收
(1)pthread_create 主线程用来创造子线程的
线程属性:__detachstate(线程间是否同步),__schedpolicy(调度策略),__schedparam(运行优先级)~~~~~~。。。。。
线程属性还可以通过函数:为了设置这些属性,POSIX定义了一系列属性设置函数,包括pthread_attr_init()、pthread_attr_destroy()和与各个属性相关的pthread_attr_get---/pthread_attr_set---函数。
join 和detch;
(2)pthread_join 主线程用来等待(阻塞)回收子线程
(3)pthread_detach 主线程用来分离子线程,分离后主线程不必再去回收子线程
大概理解就是:子线程死亡还剩下线程的栈资源,第一种是等其他线程调用join处理,第二种是设置线程属性让他自己为自己收尸;
线程取消解释
(1)pthread_cancel 一般都是主线程调用该函数去取消(让它赶紧死)子线程
(2)pthread_setcancelstate 子线程设置自己是否允许被取消
(3)pthread_setcanceltype
cancle 函数的相关实验:
1:如果子线程是默认的,可以结束,结束执行工作时立即执行的话,在父线程发结束信号,子线程会立刻结束;(有个问题,这时还需要处理栈资源吗?估计要;)
2:愁死了,一发取消信号线程就结束,说好要取消点的呢?完全不懂;
#include<stdio.h>
#include <unistd.h>
#include <pthread.h>
void* t_func(void *arg);
int main(void)
{
pthread_t tpid = -1;
int ret = -1;
ret = pthread_create(&tpid,NULL,t_func,NULL);
if (0!= ret)
{
printf("error pthread_create\n");
return -1;
}
sleep(3);
printf("wait for child thread run \n");
pthread_cancel(tpid);
return 0;
}
void* t_func(void *arg)
{
int i = 1;
int j = 0;
printf("this child thread\n");
for(j=0;j<100;j++)
{
sleep(1);
printf("i = %d second\n",i);
i++;
}
return NULL;
}
线程函数退出相关
(1)pthread_exit与return退出
(2)pthread_cleanup_push
(3)pthread_cleanup_pop
获取线程id
(1)pthread_self
备注:
p是指:posix 标准,linux是满足posix标准的;
线程函数能用return ,不能用exit(这个是进程结束返回);
注意点:线程函数出现错误不能够用perror打印?
写一个有子线程的进程:
#include<stdio.h>
#include <pthread.h>
#include<string.h>
#include <sys/types.h>
#include <unistd.h>
void* t_func(void *arg);
void printf_m(char *s)
{
pid_t pid = -1;
pthread_t tid = -1;
pid = getpid();
tid = pthread_self();
printf("%s,process id = %d ,thread id = %ld\n",s,pid,tid);
return;
}
int main(void)
{
int ret = -1;
pthread_t tid = -1;
ret = pthread_create(&tid,NULL,t_func,NULL); //线程创建
if(0!=ret)
{
printf("error pthread_create\n");
return -1;
}
printf_m("main thread\n");
//sleep(10); //不加这个进程会在子线程没执行前被结束掉;
pthread_join(tid,NULL); //或者加这个线程回收函数;
return 0;
}
void* t_func(void * arg)
{
printf_m("new thread\n");
return 0;
}
main thread
,process id = 4893 ,thread id = 140712045283136
new thread
,process id = 4893 ,thread id = 140712036767488
反思总结:NULL的含义,字符串要再看;restrict这个关键字;
线程同步 (信号量方法同步)semaphore这个信号的教程
主要是用了sem 这个函数族;
下面的程序主要是子线程得等父线程输入字符,然后才可以读取;我理解就是在一个线程设置一个断点,然后得等另一个线程发布个信号才可以执行;
//任务:用户从终端输入任意字符然后统计个数显示,输入end则结束
#include<stdio.h>
#include<string.h>
#include <unistd.h>
#include <semaphore.h>
void* t_func(void*arg);
char buf[200] = {0};
sem_t sem;
int main(void)
{
int ret = -1;
while(1)
{
printf("please input some characters,if input end this process will end\n");
scanf("%s",buf);
if (0!=strncmp(buf,"end",3))
{
sem_post(&sem);
}
else
{
return 0;
}
}
return 0;
}
void* t_func(void*arg)
{
while(1)
{
sem_wait(&sem);
printf("%s\n",buf);
memset(buf,0,sizeof(buf));
}
}
线程同步之互斥锁教程
pthread_mutex_init, pthread_mutex_lock, pthread_mutex_trylock,
pthread_mutex_unlock, pthread_mutex_destroy
条件变量
pthread_cond_init, pthread_cond_destroy, pthread_cond_signal,
pthread_cond_broadcast, pthread_cond_wait, pthread_cond_timedwait