2012.1.4
进程复习:
1. 创建 fork
2. 退出 exit _exit
3. 回收子进程状态 wait/waitpid
4. exec函数族
5. 守护进程
(1) 创建子进程,父进程退出
(2) 创建一个会话,并且以当前进程为会话组组长
(3) 与(1)步骤一样
(4) 更改进程的工作目录 chdir(”/”);
(5) 设置权限掩码 umask(0);为了守护进程创建的文件对所有用户权限相同
(6) 关闭所有的打开文件
练习:文件拷贝的例子
源文件 ------------------------- 目标文件
创建2进程。。。。。。。。
进程A 拷贝前半部分
进程B 拷贝后半部分
首先:①打开2个文件 fd(只写) fs(只读)
②获取文件大小 num = lseek(fp,0,SEEK_END)
③fork
④父进程拷贝上半部分 (涉及到file 和 f_pos)----理解???
⑤子进程拷贝下半部分
vim -d file.c file2.c 比较2文件大小
线程: 注意-----必须保证 主线程要比子线程后退出。。。。如主线程退出,不能确保子线程是否成功退出
线程:内核调度的最小单位
进程:程序执行和资源分配的最小单位
1. 每个线程都有一个tast_struct
2. 内核中,线程被称为轻量级进程。。。。。但在linux中称其为线程
3. 编程中可以使用多线程编程或者多进程编程
两者有什么区别呢:????
多进程 ------------------------------------------------------------------ 多线程
① 进程间通信A-B间数据交互 ------------------------- 多个线程tast_struct共享一个资源
所以,多线程效率高,但是数据的安全性要差(不能保持数据的一致性)
4.如何完成多线程编程????
①多线程通过第三方的线程库(new POSIX Thread Library NPTL)来实现
②线程共享的资源(与资源有关)------可执行指令,静态数据,进程中打开的文件描述符,信号处理函数
(与线程ID---TID)pc指针和相关计数器
今天的主要内容: 多线程的创建 编译线程 必须 指定的库 -lpthread
5.int pthread_create(pthread_t *thread, const pthread_attr_t *atrr, void * (*routine)(void *), void*arg)
attr : 指定线程的属性 NULL表示使用缺省属性(线程默认属性)
routine:线程的执行的函数 void * (*routine)(void *)返回值为void*,且参数为void*型的函数指针。。。。。
arg:传递给线程执行的函数的参数 NULL
返回值: 成功返回 0 失败返回 -1
获取线程号: gettid (LWP)标准库中没有这个函数 ----获得一个基于进程的ID号
.主线程退出,所有线程都退出
6. 回收子线程的状态。。。。 只需在主线程中调用。即可
int pthread_join(tid , void ** value ptr) ptr 是pthread_exit返回的状态。。。。。。
7.pthread_detach(tid) 主进程中调用,解除与主线程的关系,即子线程不需要主进程去调用pthread_join去回收子进程,。。。。。。。
8.线程的取消: 异步通知----信号的机制-----------直接将某一个线程关闭退出,不会有返回值。。。。。。
pthread_cancel(tid)
9,。线程间的同步和异步机制
怎么样才能同步?
A (数据采集)------------------------------------B (数据处理) 必须A进程先采集,并将信息告知B进程,B进程在进行数据处理
即:同步机制, 让多个进程按照预订的先后顺序执行。。。。可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B依言执行,再将结果给A;A再继续操作。
互斥机制:临界资源的互斥访问
A线程------write--临界资源 ---read -----B线程 由于时间片的问题,可能导致B线程read到不完全的数据
10.linux下提供的一机制 叫信号量。。。。。。信号量也叫信号灯-----先学习POSIX操作下的信号量。。。。。。。。。。信号量的值是非负整数
用来描述资源的个数,且一般工作在①管理资源的个数②二值信号量 0(无资源)和1(有资源)
P操作--------------------------------------------------V操作 (银行家算法)
申请资源------------------------------------------释放资源
11.死锁:当某个进程持有一个资源,却无法释放这个资源
A-------------------------------------------B
获得资源--------------------------获得资源
sleep(1)<-----------------------提供A的唤醒条件
等待B的唤醒
无法释放---------------------无法释放
因此必须尽量避免死锁。。。。。
P(S):
V(S):
12.pthread库常用的信号量操作函数:成功返回0,失败返回-1
①int sem_init(sem_t *sem, int pshared, unsigned int value)
sem 信号量,传&sem, pshared 一般为0 ,信号量初值。。。。。。
② sem_wait(sem_t *sem) 阻塞操作
③ sem_post(sem_t *sem) V操作
④ sem_trywait
⑤ 获取信号量当前状态
例程:A ------------------------------------------------------B
初始化sem_init(&sem, 0)-------------------sem_wait()
fgets() --------------------------------------------printf
sem_post +1
13.互斥的使用: 互斥的是临界资源,而使用临界资源的代码叫临界区。。。。。。。。
使用互斥锁得目的保证数据的完整性。。。。
① 互斥量
② 互斥锁
gcc file.c -lpthread -02 加上-02 系统优化编译。。。。 必须用volatile 声明这个全局变量
进程间通信
1. 无名管道:
① 凡是具有亲缘关系的进程之间的通信 (继承了进程)
② 单工模式工作------只让父进程读,子进程写,避免了子进程读出自己写入的
2. pipe(int fd[2]) fd包含2个元素的整型数组
cd /proc/ID 查看管道是否创建成功
3. 管道读写注意:
① 读端读,写端写
② 写数据,写入数据小于可写数据小于可写如数据则全部写入(PIPE_size 64kb)
写入数据大于可写数据则写入数据阻塞到可以完全写入
③ 读数据: 要读数据小于可读数据,读所需数据
。。。。。。。大于。。。。。。。,全部读出返回到实际大小
④ 对写端操作,读段必须存在