学习linux之进程,线程与通信

一,进程与线程

进程是具有一定独立功能的程序,是系统进行资源分配和调度的独立单位

线程是进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位。真正在处理机上运行的是线程。

进程与线程之间的关系:

1. 所属关系

一个线程只属于一个进程,一个进程可以拥有多个线程。

2. 资源关系

资源分配给进程,同一进程的所有线程共享该进程的所有资源。

3. 同步协调

线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

实现方式的差异

进程间的个体是完全独立的,每个进程都有独立的地址空间,一个进程无法访问另一个进程的变量和数据结构,才有了IPC。而线程间是彼此依存的。多进程环境中,任何一个进程的终止不会影响到其他进程。而多线程环境中,父线程终止,子线程被迫中止,而任何一个子线程终止一般不会影响到其他线程,除非执行exit()系统调用。

从系统实现的角度讲,进程的实现是调用fork系统调用:

pid_t fork(void);

线程的实现是调用clone系统调用,其中fork()将父进程的全部资源复制给了子进程,而线程的clone只复制了一小部分必要资源。实际中编写多进程程序采用fork和vfork创建子进程实体,创建线程时用POSIX线程库的pthread_create。

vfork和fork的两点不同:

1. vfork要等子进程返回之后父进程再运行

2. vfork创建的进程并不复制父进程的资源空间,而是共享

实体间通信方式的不同

IPC的几种方式,多线程间通信的几种方式(见下文)

控制方式的不同

进程与线程身份标识ID管理方式不一样,进程的ID为pid_t类型,实际为一个int型变量,在全系统中,进程ID是唯一标识,对于进程的管理都是通过PID来实现的,每创建一个进程,内核中创建一个结构体来存储该进程的全部信息

线程的ID是一个long型变量,系统在管理线程时需要记录其信息,在内核创建一个内核态线程与之对应,内核线程池不会被销毁或重建,它们会在必要时分配给不同的用户级线程,对线程进行资源分配管理

 

进程池和线程池技术实现的不同

数组保存进程ID,分开进程->闲置进程挂起->IPC分配任务,函数指针标记读取的任务->回收子进程

二,多线程通信方式

共享变量

线程间发送信号的一个简单方式是在共享对象的变量里设置信号值。

wait/notify机制

为了实现线程通信,我们可以使用Object类提供的wait()、notify()、notifyAll()三个方法。调用wait()方法会释放对该同步监视器的锁定。来实现synchronized线程的通信。

Lock/Condition机制

直接使用Lock对象来保持同步,则系统中不存在隐式的同步监视器对象,也就不能使用wait()、notify()、notifyAll()来协调线程的运行.而使用lock类粒度更低的condition中await/signal/signalAll机制

管道

创建管道输入流和输出流,将其匹配并赋给相应的线程,将管道输出流赋给信息输入线程,管道输入流赋给信息获取线程,就可以实现线程间的通讯了

三,进程间通信方式

管道(Pipe) :管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。

管道由调用pipe函数来创建,int pipe (int fd[2]);
 fd参数返回两个文件描述符,fd[0]指向管道的读端,fd[1]指向管道的写端。fd[1]的输出是fd[0]的输入。

(1)父进程创建管道,得到两个⽂件描述符指向管道的两端

(2)父进程fork出子进程,⼦进程也有两个⽂件描述符指向同⼀管道。

(3)父进程关闭fd[0],子进程关闭fd[1],即⽗进程关闭管道读端,⼦进程关闭管道写端(因为管道只支持单向通信)。⽗进程可以往管道⾥写,⼦进程可以从管道⾥读,管道是⽤环形队列实现的,数据从写端流⼊从读端流出,这样就实现了进程间通信。

命名管道(named pipe) :命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。

信号(Signal) :信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;Linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。

消息(Message)队列 :消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺

共享内存 :使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

内存映射(mapped memory) :内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。

信号量(semaphore) :主要作为进程间以及同一进程不同线程之间的同步手段。

套接口(Socket) :更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:linux和System V的变种都支持套接字。

socket编程
客户端通过new Socket()方法创建通信的Socket对象 ip+端口
服务器端通过new ServerSocket()创建TCP连接对象  accept接纳客户端请求 端口

参考:

https://blog.csdn.net/violet_echo_0908/article/details/51201278

https://www.nowcoder.com/discuss/84899

猜你喜欢

转载自blog.csdn.net/wannuoge4766/article/details/93968485