进程

进程间的四种通信方式

  • 管道是连接读写进程的一种特殊文件,也称为管道文件。管道文件存在于外存,其中的消息没有固定长度,能用于进程间大量的信息通信。向管道提供输入的发送进程以字符流的形式将大量的数据送入管道。接收管道输出的接收进程,从管道中接收数据。管道机制需要提供以下功能:

    • 互斥功能:当一个进程正在对管道执行读写操作时,其他进程必须等待。
    • 同步功能:当把一定数量的数据写入管道,管道出现溢出时,写进程便进入阻塞态等待,直到读进程将管道内的数据取走,再唤醒写进程。当管道为空时,读进程进入阻塞态等待,直到写进程向管道写入数据后,再唤醒读进程。
    • 确定通信双方是否存在。只有确定了对方已存在时才能进行通信。如果对方已经不存在,就没有再发送或接收消息的必要了。
  • 消息缓冲队列广泛用于本地进程之间的通信。该机制包括数据结构、发送原语和接收原语,每个进程有自己的消息缓冲队列和消息缓冲区。发送进程发送消息时,先申请一个消息缓冲区,将要发送的消息从发送进程的发送区放入消息缓冲区,然后调用发送原语将消息发送给接收进程,发送原语将发送缓冲区插入接收进程的消息缓冲队列。接收消息的进程通过调用接收原语将该进程消息缓冲队列中的消息复制到自己的消息接收区。

  • 内存共享的通信方式,相互通信的进程共享某些数据结构或共享存储区,进程之间能够通过读写共享的内存空间直接进行通信。一个进程通过操作系统将要共享的内存映射到本进程的虚拟内存空间后,具体执行访问内存的操作时可以不通过操作系统,而由地址变换机构实现对共享内存的访问。

  • 套接字进行通信时,通信的发起进程称为客户端,相应进程称为服务器。通信前双方需要建立连接,通信结束后还应该关闭连接。数据传送过程中双方需要同步以保证传输数据的正确性。

  • 注意

    • 消息缓冲队列和内存共享方式都通过内存进行通信,所以速度快。但消息缓冲队列要求操作系统内核的参与,每次发送或接收数据都要通过操作系统,而共享内存方式允许进程直接访问共享的数据区,在访问过程中省掉了进入内核等许多费时的环节,因而内存共享是速度最快的通信方式
    • 套接字:客户端和服务器进行连接时,客户端只连接一次(发送connect连接),当我们错误的先打开服务器,再打开客户端,会错失连接机会。此时,我们需要要求服务器一直侦听连接请求,完成连接。(以Qt为例,可以定义QTimer定时器,一直侦听连接请求,直至连接成功,关闭定时器。另Qt中有waitForConnected()函数:等待链接的建立。)

进程通信与线程通信的区别

  • 不同的进程:进程之间相互独立,具有不同的地址空间,必须通过进程间通信机制完成。(管道、消息缓冲队列、共享内存、套接字)

  • 进程的不同线程:共享同一地址空间,可以通过共享内存区域直接通信。(每个线程必须有自己的栈,反映自己特定的执行情况。

创建进程

  • 申请空白PCB(进程控制块)

  • 为新进程分配资源(包括内存)

  • 初始化进程控制块

  • 新进程插入就绪队列

进程(作业)调度算法

  • 先来先服务调度算法:按照进程到达的先后次序分配CPU。

  • 高响应比优先调度算法:把响应作为一种动态优先权,优先把CPU分配给响应比高的进程。采用该调度算法时,对于等待时间相同,需要服务时间较少的进程,其响应比较高,将优先获得CPU。对于需要服务时间相同的进程,随着等待时间的增加,其响应比也随之增加,优先获得CPU。

    • =+/ 进 程 的 响 应 比 = ( 进 程 等 待 时 间 + 进 程 需 要 的 服 务 时 间 ) / 进 程 需 要 的 服 务 时 间
  • 时间片轮转调度算法:系统为每个进程分配一个时间片,进程按照进入就绪队列的先后次序轮流在CPU上执行固定的时间片。所有进程都有均等的机会得到运行。

  • 抢占式调度算法:当前正在运行的进行可能被暂停执行,进入就绪队列,CPU可以被系统分配给其他进程。

  • 非抢占式调度算法:一旦进程获得CPU处于执行状态,就一直执行到进程结束,除非因为进程本身的某种原因而自我阻塞。

  • 短作业优先调度算法:优先把CPU分配给短作业,采用该调度算法时,若系统不断有短任务进入就绪队列,长任务可能会因无限等待CPU而进入饥饿状态。

进程的周转时间

  • = 周 转 时 间 = 进 程 完 成 的 时 间 − 进 程 到 达 的 时 间
1. 实验目的 1) 加深对进程概念的理解,明确进程和程序的区别。 2) 进一步认识并发执行的实质。 3) 分析进程争用资源的现象,学习解决进程互斥的方法。 4) 学习解决进程同步的方法。 5) 了解Linux系统中进程通信的基本原理。   进程是操作系统中最重要的概念,贯穿始终,也是学习现代操作系统的关键。通过本次实验,要求理解进程的实质和进程管理的机制。在Linux系统下实现进程从创建到终止的全过程,从中体会进程的创建过程、父进程和子进程之间的关系、进程状态的变化、进程之间的互斥、同步机制、进程调度的原理和以管道为代表的进程间的通信方式的实现。 2. 内容及要求:   这是一个设计型实验,要求自行编制程序。   使用系统调用pipe()建立一条管道,两个子进程分别向管道写一句话:   Child process1 is sending a message!   Child process2 is sending a message!   父进程从管道读出来自两个子进程的信息,显示在屏幕上。   要求: 1) 父进程先接收子进程1发来的消息,然后再接收子进程2发来的消息。 2) 实现管道的互斥使用,当一个子进程正在对管道进行写操作时,另一子进程必须等待。使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定。 3) 实现父子进程的同步,当子进程把数据写入管道后,便去睡眠等待;当父进程试图从一空管道中读取数据时,也应等待,直到子进程将数据写入管道后,才将其唤醒。 3.相关的系统调用 1) fork() 用于创一个子进程。 格式:int fork(); 返回值:在子进程中返回0;在父进程中返回所创建的子进程的ID值;当返回-1时,创建失败。 2) wait() 常用来控制父进程与子进程的同步。 在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,父进程从wait()返回继续执行原来的程序。 返回值:大于0时,为子进程的ID值;等于-1时,调用失败。 3) exit() 是进程结束时最常调用的。 格式:void exit( int status); 其中,status为进程结束状态。 4) pipe() 用于创建一个管道 格式:pipe(int fd); 其中fd是一个由两个数组元素fd[0]和fd[1]组成的整型数组,fd[0]是管道的读端口,用于从管道读出数据,fd[1] 是管道的写端口,用于向管道写入数据。 返回值:0 调用成功;-1 调用失败。 5) sleep() 调用进程睡眠若干时间,之后唤醒。 格式:sleep(int t); 其中t为睡眠时间。 6) lockf() 用于对互斥资源加锁和解锁。在本实验中,该调用的格式为: lockf(fd[1],1,0);/* 表示对管道的写入端口加锁。 lockf(fd[1],0,0);/* 表示对管道的写入端口解锁。 7) write(fd[1],String,Length) 将字符串String的内容写入管道的写入口。 8) read(fd[0],String,Length) 从管道的读入口读出信息放入字符串String中。 4.程序流程 父进程: 1) 创建管道; 2) 创建子进程1; 3) 创建子进程2; 4) 等待从管道中读出子进程1写入的数据,并显示在屏幕上; 5) 等待从管道中读出子进程2写入的数据,并显示在屏幕上; 6) 退出。 子进程: 1) 将管道的写入口加锁; 2) 将信息“Child process n is sending message!”输入到变量OutPipe中,n=1,2; 3) 将OutPipe中信息写入管道; 4) 睡眠等待; 5) 将管道的写入口解锁; 6) 退出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值