C语言项目(三)——基于Linux系统下的带有GUI界面的即时通信软件

十.多线程与多进程通信方式的区别?

引入线程的好处

(1)易于调度。

(2)提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一程序的不同部分。

(3)开销少。创建线程比创建进程要快,所需开销很少。

(4)利于充分发挥多处理器的功能。通过创建多线程进程(即一个进程可具有两个或更多个线程),每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分运行。

进程和线程的关系:

(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

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

(3)处理机分给线程,即真正在处理机上运行的是线程。

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

线程是指进程内的一个执行单元,也是进程内的可调度实体.

进程间的通信方式:

1.管道(pipe)及有名管道(named pipe):

管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。

2.信号(signal):

信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。

3.消息队列(message queue):

消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。

4.共享内存(shared memory):

可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。

5.信号量(semaphore):

信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。主要作为进程之间及同一种进程的不同线程之间得同步和互斥手段。

6.套接字(socket);

这是一种更为一般得进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。

      线程间的通信方式

1. 锁机制:包括互斥锁、条件变量、读写锁

   *互斥锁提供了以排他方式防止数据结构被并发修改的方法。

   *读写锁允许多个线程同时读共享数据,而对写操作是互斥的。

   *条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。

2. 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量

3. 信号机制(Signal):类似进程间的信号处理

    线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。

十一.谈谈你对进程的理解,内核是如何管理进程的?

  • 进程是计算机中处于运行中的程序的实体
  • 线程是最小的运行单位,而进程是线程的容器
  • 程序本身只是指令、数据及其组织形式的描述,进程才是程序(指令和数据)的真正运行实例

一、程序与进程

  • Linux进程结构一般由三部分组成:代码段、数据段和堆栈段
  • 代码段:用于存放程序代码的数据:如果机器中有多个进程运行相同的一个程序,那么它们就可以使用同一段代码
  • 数据段:存放程序的全局变量、常量和静态变量
  • 堆栈段:栈用于函数调用,存放函数的参数、函数内部定义的局部变量。堆栈段中还包括了进程控制块(Process Control Block,PCB)
  • PCB处于进程核心堆栈的底部,不需要额外分配空间。PCB是进程存在的唯一标识,系统通过PCB的存在而感知进程的存在。系统通过PCB对进程进行管理和调度。PCB包括创建进程、执行程序、退出进程以及改变进程的优先级等
  • Linux下C++程序的生成可以分为4个阶段:预处理、编译、汇编、链接     第四章编译
  • 一般程序转换为进程分以下几个步骤:

1.内核将程序读入内存,为程序分配内存空间                //为程序分配

2.内核为该进程分配进程标识符PID和其他所需资源           //为进程分配

3.内核为进程保存PID及相应的状态信息,把进程放到运行队列中等待执行,程序转化为进程后可以被操作系统的调度程序调度执行了

  • 每个进程在系统中都有一个唯一的ID标识它,这个ID就是进程标识符(PID)。因为其唯一性,所以系统可以根据PID准确定位到一个进程
  • 进程标识符的类型为pid_t,本质上是一个无符号整形的类型别名
  • 程序是可运行的二进制代码文件,把这种文件加载到内存中运行就得到了一个进程(所以你每打开一个程序都会占用一部分系统内存)
  • 同一个程序文件可以被加载多次成为不同的进程(你可以打开两个QQ)。进程与进程标识符之间是一对一的关系,而程序与进程之间是一对多的关系

二.内核是如何管理进程的?

  进程管理负责控制进程对 CPU 的访问,如任务的创建、调度和终止等。任务调度是进程管理最核心的工作,由 Linux 内核调度器来完成。linux 内核调度器根据进程的优先级选择最值得运行的进程。

      一个进程的可能状态有如下几种:

    (1)  运行态——已经获得了资源,并且进程正在被 CPU 执行。进程既可运行在内核态,也可运行在用户态。

    (2)  就绪态——当系统资源已经可用,但由于前一个进程还没有执行完释放  CPU,准备进入运行状态。

    (3)  可中断睡眠状态——当进程处于可中断等待状态时,系统不会调度该程序执行。当系统产生一个中断或者释放了进程正在等待的资源,或者进程收到一个信号,都可以被唤醒进入就绪状态或者运行态。

    (4)  不可中断睡眠状态——处于中断等待状态,但是该进程只能被使用  wake_up()函数明确唤醒的时候才可进入就绪状态。

    (5)  暂停状态——当进程收到 SIGSTOP、SIGSTP、SIGTTIN 或者 SIGTTOU 就会进入暂停状态,收到 SIGCONT 信号即可进入运行态。

    (6)  僵死态——进程已经停止运行,但是其父进程还没有询问其状态。

十三.什么是进程死锁?操作进程死锁的原因是什么?

什么是死锁

所谓死锁:是指多个进程在运行过程中因争夺资源而造成的一种僵局。

产生死锁的原因

l  竞争资源:当系统中多个进程使用共享资源,并且资源不足以满足需要,会引起进程对资源的竞争而产生死锁。

l  进程间推进的顺序非法:请求和释放资源的顺序不当,也同样会导致产生进程死锁

产生死锁的必要条件

  1. 互斥条件:进程对所分配到的资源进行排它性使用,在一段时间内某资源只由一个进程占用。
  2. 请求和保持条件:指一个进程已经保持了至少一个资源,但又提出新的资源请求,而此资源被其他占用,此时请求进程阻塞,但又对自己已经占用的资源保持不放。
  3. 不剥夺条件:进程已经获得资源,在未使用完之前,不能被剥夺,只能在使用完时,由进程自己释放。
  4. 环路等待条件:发生死锁时,必然存在一个进程-资源的环形链。

处理死锁的方法

l  预防死锁

事先预防,破坏产生死锁的四个必要条件之一。

  1. 摒弃“请求和保持”条件:

进程在申请资源时,是一次性的。

如何摒弃“请求“:当进程来时,一次性分配所有的资源(如果系统满足),这样就不会再有”请求“了。

如何摒弃“保持“:只要有一个资源得不到分配,也不给这个进程分配其他的资源。

  1. 摒弃“不剥夺”条件:在这种方法中,进程是逐个提出对资源的要求的。如果一个进程,获得了部分资源,但得不到其它资源,这时,它释放自己所占用的资源。
  2. 摒弃“环路等待”条件:把资源排序,当进程申请资源时,按序申请。

l  避免死锁

事先预防,并不是破坏产生死锁的四个必要条件,而是用某种方法去防止系统进入不安全状态,目前在较完善的系统中,常用此方法。银行家算法

安全状态:是指系统能按照某种进程顺序(P1,P2,…Pn),来为每一个进程Pi分配其所需要的资源,直到满足每个进程对资源的最大需求,使每个进程都可顺利地完成。如果系统无法找到这样一个安全序列,则称系统处于不安全状态。

l  检测死锁

并不事先采取任何限制性的措施,也不必检查系统是否已经进入不安全区,此方法允许发生死锁,关键是,发生死锁了,系统可以通过检测机构发现死锁,并精确确定与死锁有关的进程和资源,然后,采取适当措施,从系统中将已经发生的死锁清除

l  解除死锁

这是与检测死锁配套使用。当检测到系统已经发生了死锁,要将进程从死锁状态中解脱出来。常用的方法是撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已经处于阻塞状态的进程,使之转为就绪状态,以继续运行。

十四.保持进程同步的方法有哪些?

Linux 下:

Linux 下常见的进程同步方法有:SysVIPC 的 sem(信号量)、file locking / record locking(通过 fcntl 设定的文件锁、记录锁)、futex(基于共享内存的快速用户态互斥锁)。针对线程(pthread)的还有 pthread_mutex 和 pthread_cond(条件变量)。
 
Linux 下常见的进程通信的方法有 :pipe(管道),FIFO(命名管道),socket(套接字),SysVIPC 的 shm(共享内存)、msg queue(消息队列),mmap(文件映射)。以前还有 STREAM,不过现在比较少见了(好像)。

Windows下:
在Windwos中,进程同步主要有以下几种:互斥量、信号量、事件、可等计时器等几种技术。

在Windows下,进程通信主要有以下几种:内存映射、管道、消息等,但是内存映射是最基础的,因为,其他的进程通信手段在内部都是考内存映射来完成的。

十五.线程同步方式有哪些?优缺点?

现在流行的进程线程同步互斥的控制机制,其实是由最原始,最基本的4中方法实现的:

1.临界区:通过多线程的互串行访问公共资源或一段代码,速度快,适合控制数据访问。

2.互斥量:为协调共同对一个共享资源的单独访问而设计。只有拥有互斥对象的线程才有权限去访问系统的公共资源,因为互斥对象只有一个,所以能够保证资源不会同时被多个线程访问。

3.信号量:为控制一个具有有限数量的用户资源而设计。它允许多个线程在同一时刻去访问同一个资源,但一般需要限制同一时刻访问此资源的最大线程数。

4.事件:用来通知线程有一些事件已发生,从而启动后继任务的开始。

十七.如何实现文件传输?如果文件过大,如何保证数据正确的传输?

(1)客户端之间传输文件

A、B两用户登录服务器成功之后,便可使用文件传输API接口传送文件,当A使用API接口:BRAC_TransFile向B发送文件时,B收到文件后,将触发B的回调函数:文件传输回调函数(参考:BRAC_SetTransFileCallBack

内核使用UDP通道传输,不保证接收方收到的顺序与发送顺序相同,但是保证数据可达,丢包自动重传;

 (2) 

18、文件传输的过程会占用比较多的资源,如何解决? 

19、TCP与UDP的区别

  • TCP和UDP编程区别

TCP编程的服务器端一般步骤是: 
  1、创建一个socket,用函数socket(); 
  2、设置socket属性,用函数setsockopt(); * 可选 
  3、绑定IP地址、端口等信息到socket上,用函数bind(); 
  4、开启监听,用函数listen(); 
  5、接收客户端上来的连接,用函数accept(); 
  6、收发数据,用函数send()和recv(),或者read()和write(); 
  7、关闭网络连接; 
  8、关闭监听; 

  TCP编程的客户端一般步骤是: 
  1、创建一个socket,用函数socket(); 
  2、设置socket属性,用函数setsockopt();* 可选 
  3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
  4、设置要连接的对方的IP地址和端口等属性; 
  5、连接服务器,用函数connect(); 
  6、收发数据,用函数send()和recv(),或者read()和write(); 
  7、关闭网络连接;


  与之对应的UDP编程步骤要简单许多,分别如下: 
  UDP编程的服务器端一般步骤是: 
  1、创建一个socket,用函数socket(); 
  2、设置socket属性,用函数setsockopt();* 可选 
  3、绑定IP地址、端口等信息到socket上,用函数bind(); 
  4、循环接收数据,用函数recvfrom(); 
  5、关闭网络连接; 

  UDP编程的客户端一般步骤是: 
  1、创建一个socket,用函数socket(); 
  2、设置socket属性,用函数setsockopt();* 可选 
  3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
  4、设置对方的IP地址和端口等属性; 
  5、发送数据,用函数sendto(); 
  6、关闭网络连接;

20、什么时候选择TCP和UDP

TCP:面向连接、可靠的通信方式,适用于传输大量数据、对可靠性要求高的场合
UDP:无连接、不可靠的通信方式,但由于无连接,传送速度较快,适用于对可靠性要求不高、数据量较小,速度要求较快的场合。

猜你喜欢

转载自blog.csdn.net/zhanganliu/article/details/81319898