多线程和多进程一些知识点


什么是指令
代码写好之后,可执行文件里面就是指令,cpu可以直接执行,也就是机器语言,现在比较多的有x86和x64指令集合。

什么是上下文
就是指一种环境,只有在并发操作上才会用到,因为cpu并不是真正的并发,在一个函数时间片用完时,然而这个函数还没执行完,它就必须把这个函数的相关信息记录下来,比如临时变量名,值,下一步该执行到哪条指令。这样才能在接下来很顺利的执行这个函数。

什么是环境变量
一般指参数,linux下直接输入env可查看这些参数,是可以自己定义的。举个例子,如果是一个人,那他的环境变量就是对他身边周围的描述,比如住在哪里,兴趣爱好。然后在他发生某些事件,其实这时候相当于软件要完成一些功能,比如不想工作了想休息,这时候电脑就会调用你的兴趣爱好这个参数。

进程的相关操作
linux下,2个进程号要记住,进程0负责调度进程的进程,进程1负责init的进程
ps -a当前运行的进程打印出来
killall process(进程名)杀死一个进程
top -p 进程号  每隔5s在屏幕上刷新一下进程的信息

线程
创建线程的库不是linux的默认库,编译的时候需要加上-lpthread
4个重要函数:pthread_create(线程标识符,线程属性一般是NULL,线程运行函数初始地址,一个函数指针,给第三个参数传递参数的参数)
void thread(void *p)
{
 int i = 0;
 int*q =(int *)p;
 while(1)
{
 printf("thread param is %d:",*q);
 sleep(2);
}
return 0;
}
int main()
{
int res = 0;
pthread_t T1;
res = pthread_create(&T1,NULL,(void *)thread,&para);
if(0!=res)
{
 printf("thread start failed\n");
 return 0;
}
while(1)
{
 printf("main_thread:%d\n",k++);
 sleep(2);
}
return 0;
}
第二个函数:
pthread_t T1;
pthread_cancel(T1);需要一个取消点,不会马上取消。sleep就是一个取消点,能引起线程阻塞的函数一般都是取消点,可以手动增加取消点pthread_testcancel()。
第三个函数
pthread_exit();
在线程的循环里直接调用;
第四个函数
pthread_join(T1,NULL);
将会等待T1线程结束
线程私有数据
每个线程都可以访问自己的数据副本,不需要担心与其他线程的同步问题,这个比较特殊,线程和进程是不一样的,线程没有属于自己的内存空间。常见的线程私有数据有,线程id(这个好理解,不可能别人和我有一样的id吧),errno(操作失败的返回值),寄存器,调度优先级,信号屏蔽字(创建线程的时候,线程继承进程的信号屏蔽字)。
线程的5种状态
new,running,ready,blocked,exit
好用的函数
给线程起名字
#include<sys/prctl.h>
prctl(PR_SET_NAME,"线程名");
线程特别说明:一个进程至少包括一个线程,每个线程按照时间片来执行的,线程是系统调度的最小单位。


很重要,线程的同步
比如一个线程对变量a进行读取,另一个线程对变量a进行修改,这样就有可能导致数据的不一致性,甚至产生段错误,一般来说,段错误就是踩地址,访问了非法空间。
解决同步的方法就是让2个线程互斥,我操作数据的时候你不能操作,你操作数据的时候我不能操作。
如何做到互斥呢,就是上锁,三个步骤,初始化锁,上锁,解锁
pthread_mutex mutex;
int pthread_mutex_init(&mutex,锁的属性,默认为空);
int pthread_mutex_lock(&mutex);
int pthread_mutex_unlock(&mutex);
还有一个函数int pthread_mutex_trylock(&mutex);试着获取锁,获取不到不会发生阻塞,能够节省性能。
但是这样有可能会造成一种阻塞现象,因为竞争资源或者由于彼此通信,若无外力作用,它们无法继续推进下去,此时称系统产生了死锁,就是第一个线程获取到了第一个锁,接着还要获取第二个锁,但是很不巧第二个锁被第二个线程获取了,然而第二个线程接下来想要获取第一个锁,就会产生死锁。
死锁的四个必要条件:
互斥条件,某资源只能由一个线程占用
请求和保持条件,请求另一个资源,而这个资源别人占用了,而且还保持自己的资源不放
不剥夺条件,已获得的资源,只能使用完自己释放
环路等待,资源的环形链,他爱她,她爱他,他爱他,没有人会幸福
进程
一个软件至少包括一个进程,一个进程至少包含一个线程,很多嵌入式或者单片机不支持多线程。
什么是进程
一个具有独立功能的程序,是关于某个数据集合的一次运行活动,它可以申请和拥有系统资源,是一个动态的概念。
可执行文件解析
代码编译之后,可执行文件里面到底有哪些呢
正文段:text段,其实就是代码区,父子进程共享他,只读
初始化数据段:data段,只放初始化的变量,如全局变量,静态变量,const修饰的变量
未初始化数据段:bss段,在程序执行之前,内核将此段中的数据初始化为0,或者null,未初始化的全局变量就放在这里。
堆:动态存贮空间的分配,malloc函数分配内存,这个内存空间就是堆管理的
栈:自动变量和每次函数调用所需保存的信息都存在此段中,栈的空间是有限的,所以临时变量不能占用太多的空间,比如在函数里面的要定义一个超大的数组,就用malloc申请
ulimit -s可以查看栈的空间大小
多进程编程
多进程编程比多线程编程多了一层意思,就是多线程必须在一个进程里面创建多个线程,而多进程可以在一个进程里面创建多个进程,这样就是父子进程的关系。也可以2个完全独立的进程相互配合完成软件功能。
fork函数和vfork函数
fork一次调用,2次返回值,父子谁先不知道。
vfork保证子进程先运行
exit()
关闭所有文件,终止正在执行的程序
在关闭之前会把缓冲中的数据刷新到对应的设备上(硬盘或者显示器)
在fork里面调用exit()是错误的,因为会导致标准输入输出缓存区被清空2次,临时文件会被意外的删除
exit(0)表示正常,其他都是不正常,正常退出时和return一样,就算不在main里面调用exit(),也会结束程序
适用的大部分情况是进入一个main 一个exit
_exit( )就不会刷数据下去,如果要保证数据完整性,就要适用exit()
虚拟存贮器
操作系统用来骗进程告诉他这些内存是你独占的,称之为虚拟地址空间叫做堆
pcb是进程存在的唯一标志,操作系统就是控制这块数据结构从而达到控制进程的效果,他是进程实体的一部分。
僵尸进程
当一个进程终止,就算是正常的,内核并不是立即把它从系统中清除,终止未被清除的就叫僵尸进程
避免僵尸进程的方法
wait和waitpid
把父进程杀掉





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值