Linux进程&线程
2015-06-16 22:54
471 查看
1.进程
进程的引入是因为为了满足多用户多任务的操作的需要,对于每个任务需要分别分配一个进程进行控制。对于每个进程很显然要标识它所拥有的资源。所以这里就引入了PCB(process control block)这个概念,对于每个PCB会有保存的各个资源变量。当你有了PCB的概念后,紧接着就是面临三个问题就是。
1.如何创建一个进程
2. 在新建的一个进程里如何执行自己的程序
3. 创建的函数如何回收资源
这样就引出了三个函数,fork(),execve()以及wait()函数。fork()函数是创建新进程的函数,通过一次调用两次返回,来实现对父进程以及子进程的判断。execve是在新创建的进程中如何load用户想执行程序的函数。execve函数分为以下几个函数。
其中函数中如果缺少字母p(path) l(list) e(enviroment)则在参数中必须给出。其中execve是系统调用,其它的函数实际上还是调用它来完成功能。
wait()函数是清理子进程的函数。如果一个进程结束了,父进程没有调用wait()对其清理的话,那么这个进程叫做僵尸进程。而如果父进程结束了,而子进程未结束,那么这个进程的父进程改为init进程,init进程会自动清理子进程。处理僵尸进程的一个方法是利用信号来处理,因为子进程结束时会给父进程发送SIGCHILD信号,这时父进程把该信号的默认处理函数改为清理函数即可。
对于wait以及waitpid主要有两个方面的区别
1. waitpid可以通过pid指定要清理的进程
2.其中OPTIONS指定WNOHANG可以使得waitpid不阻塞
另一个话题就是进程间的通信问题。
linux进程间的通信方法总结如下
通过fork函数把打开文件的描述符传递给子进程
通过wait得到子进程的终结信息
通过加锁的方式,实现几个进行共享读写某个文件
进行间通过信号通信,SIGUSR1和SIGUSR2实现用户定义功能
利用pipe进行通信
FIFO文件进行通信
mmap,几个进程映射到同一内存区(其中有个MAP_SHARED参数)
SYS IPC 消息队列,信号量(很少用)
UNIX Domain Socket,常用
其中利用pipe函数是在内核中开辟一个缓冲区进行数据的传送,但是如果通信的进程间没有从公共的父进程哪里继承文件描述符,那么要考虑使用FIFO/Socket文件进行通信,因为文件的位置是一定的,FIFO以及Socket其实不是实际存在的文件,只是用来表示内核通道的文件。
2.线程
因为进程在创建以及切换的过程中消耗的资源很大,所以就引入了线程的手段。线程其实也被称作轻量集的进程。所以这里我们也可以利用学习进程的三个方面的问题来学习线程。
1.如何创建线程
2.如何在线程中加载要运行的函数。
3.如何回收/结束创建的线程
这里线程的创建以及加载运行所要的函数都是通过pthread_create函数来实现的。
其中thread是线程的pid,start_routine是线程要执行的函数指针, arg是其参数。attr则是指的线程的属性。
结束某个线程而又不结束整个进程,可以有三个方法。
1. 从线程函数return,
2. pthread_cancel终止同一个进程的另一个线程
3. pthread_exit终止自己
与waitpid一样我们有时也需要获取结束线程是否成功,这样就引入了pthread_join()函数
其主要作用是挂起等待线程的结束,并通过vaule_ptr返回其值。
由于线程中很多资源都是进程中共享的,当频繁的对进程进行读写操作的时候,很容易产生访问共享数据冲突的情形,所以需要引入锁来解决这个问题。
其中lock以及trylock的区别是一个会阻塞,一个不会阻塞。锁所带来的一个问题就是死锁问题,死锁就是多个线程加锁与解锁的顺序不对导致其全部阻塞。这里为了防止死锁。首先要尽量避免多次同时获取多个锁。实在无法避免则所有的线程按照顺序获取与释放,如获取锁1,锁2,锁3,释放锁1,锁2,锁3.如果这个都无法保证那么就使用trylock来代替lock。
另外线程间同步机制还有其它两种方式分别是条件变量以及信号量。
条件变量的同步主要是为了满足这样的一个条件,那就是当线程A阻塞时,需要线程B在某个时间唤醒它。也就是说通过线程B给其发信号。而信号量则主要是可是实现多个线程可以同时进行的锁。互斥锁可以看作其一种特殊的情形。信号量也可以使用在进程间同步中。
线程间通信方式如下
锁机制
信号量机制
信号机制
全局变量
参数传递
3. 线程与进程的比较
地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
线程是处理器调度的基本单位,但进程不是.
二者均可并发执行.
进程的引入是因为为了满足多用户多任务的操作的需要,对于每个任务需要分别分配一个进程进行控制。对于每个进程很显然要标识它所拥有的资源。所以这里就引入了PCB(process control block)这个概念,对于每个PCB会有保存的各个资源变量。当你有了PCB的概念后,紧接着就是面临三个问题就是。
1.如何创建一个进程
2. 在新建的一个进程里如何执行自己的程序
3. 创建的函数如何回收资源
这样就引出了三个函数,fork(),execve()以及wait()函数。fork()函数是创建新进程的函数,通过一次调用两次返回,来实现对父进程以及子进程的判断。execve是在新创建的进程中如何load用户想执行程序的函数。execve函数分为以下几个函数。
#include <unistd.h> int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ..., char *const envp[]); int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]); int execve(const char *path, char *const argv[], char *const envp[]);
其中函数中如果缺少字母p(path) l(list) e(enviroment)则在参数中必须给出。其中execve是系统调用,其它的函数实际上还是调用它来完成功能。
wait()函数是清理子进程的函数。如果一个进程结束了,父进程没有调用wait()对其清理的话,那么这个进程叫做僵尸进程。而如果父进程结束了,而子进程未结束,那么这个进程的父进程改为init进程,init进程会自动清理子进程。处理僵尸进程的一个方法是利用信号来处理,因为子进程结束时会给父进程发送SIGCHILD信号,这时父进程把该信号的默认处理函数改为清理函数即可。
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options);
对于wait以及waitpid主要有两个方面的区别
1. waitpid可以通过pid指定要清理的进程
2.其中OPTIONS指定WNOHANG可以使得waitpid不阻塞
另一个话题就是进程间的通信问题。
linux进程间的通信方法总结如下
通过fork函数把打开文件的描述符传递给子进程
通过wait得到子进程的终结信息
通过加锁的方式,实现几个进行共享读写某个文件
进行间通过信号通信,SIGUSR1和SIGUSR2实现用户定义功能
利用pipe进行通信
FIFO文件进行通信
mmap,几个进程映射到同一内存区(其中有个MAP_SHARED参数)
SYS IPC 消息队列,信号量(很少用)
UNIX Domain Socket,常用
其中利用pipe函数是在内核中开辟一个缓冲区进行数据的传送,但是如果通信的进程间没有从公共的父进程哪里继承文件描述符,那么要考虑使用FIFO/Socket文件进行通信,因为文件的位置是一定的,FIFO以及Socket其实不是实际存在的文件,只是用来表示内核通道的文件。
2.线程
因为进程在创建以及切换的过程中消耗的资源很大,所以就引入了线程的手段。线程其实也被称作轻量集的进程。所以这里我们也可以利用学习进程的三个方面的问题来学习线程。
1.如何创建线程
2.如何在线程中加载要运行的函数。
3.如何回收/结束创建的线程
这里线程的创建以及加载运行所要的函数都是通过pthread_create函数来实现的。
#include <pthread.h> int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void*), void *restrict arg);
其中thread是线程的pid,start_routine是线程要执行的函数指针, arg是其参数。attr则是指的线程的属性。
结束某个线程而又不结束整个进程,可以有三个方法。
1. 从线程函数return,
2. pthread_cancel终止同一个进程的另一个线程
3. pthread_exit终止自己
与waitpid一样我们有时也需要获取结束线程是否成功,这样就引入了pthread_join()函数
#include <pthread.h> int pthread_join(pthread_t thread, void **value_ptr);
其主要作用是挂起等待线程的结束,并通过vaule_ptr返回其值。
由于线程中很多资源都是进程中共享的,当频繁的对进程进行读写操作的时候,很容易产生访问共享数据冲突的情形,所以需要引入锁来解决这个问题。
#include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex); int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);
其中lock以及trylock的区别是一个会阻塞,一个不会阻塞。锁所带来的一个问题就是死锁问题,死锁就是多个线程加锁与解锁的顺序不对导致其全部阻塞。这里为了防止死锁。首先要尽量避免多次同时获取多个锁。实在无法避免则所有的线程按照顺序获取与释放,如获取锁1,锁2,锁3,释放锁1,锁2,锁3.如果这个都无法保证那么就使用trylock来代替lock。
另外线程间同步机制还有其它两种方式分别是条件变量以及信号量。
条件变量的同步主要是为了满足这样的一个条件,那就是当线程A阻塞时,需要线程B在某个时间唤醒它。也就是说通过线程B给其发信号。而信号量则主要是可是实现多个线程可以同时进行的锁。互斥锁可以看作其一种特殊的情形。信号量也可以使用在进程间同步中。
线程间通信方式如下
锁机制
信号量机制
信号机制
全局变量
参数传递
3. 线程与进程的比较
地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
线程是处理器调度的基本单位,但进程不是.
二者均可并发执行.
相关文章推荐
- Redhat/CentOS系统KVM虚拟机安装过程详解
- 夸平台telnet
- linux用户的秘密之login.defs文件详解
- CentOS开启FTP及配置用户
- Linux_3.1_静态函数库设计
- linux笔记之vim(cent os)
- Linux开机启动过程
- Linux 配置 nfs
- Linux Rootkit之二:Linux模块加载与信息隐藏
- phpstudy在linux下的初体验-----php文件放置目录
- 怎样在win7上远程连接linux系统
- window远程连接linux
- windows 远程连接linux服务器
- Linux asyn-io for socket
- CentOS 安装mysql
- 连接远程LINUX服务器
- Linux 多核下绑定硬件中断到不同 CPU(IRQ Affinity)
- Linux 开机自动挂载分区
- linux下xampp的MySQL配置
- linux 分区格式查看