操作系统

///------进程-------//

1  ⑴进程

①是进程实体的运行过程是系统进行资源分配和调度的一个独立单位。

②一个进程映像(进程实体)= 程序段 + 数据段 + PCB()

  a 程序段:程序段就是能被进程调度程序调度到CPU执行的程序代码段。注意,程序可以被多个进程共享,就是说多个进程可以运行同一个程序。

  b 数据段:一个进程的数据段,可以是进程对应的程序加工处理的原始数据,也可以是程序执行时产生的中间或最终结果。

  c 进程控制块:用PCB来描述进程的基本情况和运行状态,进而控制和管理进程。

③PCB是进程存在的唯一标志。(创建进程就是创建PCB,撤销进程就是撤销PCB)

  ⑵进程特征

    进程具有动态性,并发性,独立性,异步性和结构性(结构上分为三部分程序段,数据段,PCB)。

2 进程和程序的关系

  ①进程和程序的组成不同,进程是由程序、数据和PCB三部分组成,而程序是一组有序的指令集合,进程是程序的一次执行过程,是一个动态的概念,而程序是一种静态的概念;

②进程的运行实体是程序,离开程序的进程没有存在的意义;

③进程是一个程序及其数据在处理机上顺序执行时所发生的活动,具有一定的生命周期,而程序则是一组代码的集合,它是永久存在的,可以长风器保存;

④一个进程可以执行一个或者多个程序,一个程序也可以构成多个进程,进程可以创建进程,而程序不可以形成新的程序。

3  进程状态转换

①进程的5种状态之间的转换实际上就是三种基本状态(就绪,运行,阻塞)之间的转换;

就绪状态 -> 运行状态:处于就绪状态的进程被调度后,获得处理机资源(分派处理机时间片),于是进程由就绪状态转换为运行状态。

运行状态 -> 就绪状态:处于运行状态的进程在时间片用完后,不得不让出处理机,从而进程由运行状态转换为就绪状态。此外,在可剥夺的操作系统中,当有更高优先级的进程就、 绪时,调度程度将正执行的进程转换为就绪状态,让更高优先级的进程执行。

运行状态 -> 阻塞状态:当进程请求某一资源(如外设)的使用和分配或等待某一事件的发生(如I/O操作的完成)时,它就从运行状态转换为阻塞状态。进程以系统调用的形式请求操作系统提供服务,这是一种特殊的、由运行用户态程序调用操作系统内核过程的形式。

阻塞状态 -> 就绪状态:当进程等待的事件到来时,如I/O操作结束或中断结束时,中断处理程序必须把相应进程的状态由阻塞状态转换为就绪状态。

 

4 进程同步:顺序执行程序,多个进程相互配合共同完成一项任务。

  进程并发:同时发生

 进程互斥:由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥。

  临界资源(互斥资源):系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源。

  临界区:在程序中涉及到互斥资源的程序段叫临界区。

5 进程间通信的目的

  ①数据传输:

  ②资源共享

  ③通知事件:一个进程需要向另一个或者一组进程发送消息,通知它发生了某事件。(如进程终止时要通知父进程)

  ④进程控制:有些进程希望完全控制另外一个进程的执行(如Debug进程)

6 进程间通信方式

   ① 文件:一个进程把数据写到文件里,另一个进程读取;

   ② 管道(pipe):半双工管道无边界,无类型,传输的是字节流,管道先进先出,必须是有亲缘关系的进程间通信;

   ③ 有名管道(FIFO):半双工

   ④ 消息队列:使用于两个进程之间的通信,首先在一个进程中创建消息队列,然后再往消息队列中写数据,而另一个进程则是从消息队列中取数据。需要注意的是,消息队列使用创建文件的方式建立的,如果一个进程想某个消息队列中写入了数据之后,另一个进程并没有取出数据,即使像消息队列中协数据的进程已经结束,保存在消息队列中的数据并没有消失,也就是说下次再从消息队列中读取数据的时候,还是上次的数据。

   ⑤ 共享内存:

   ⑥ 信号量:基于计数

   ⑦ 套接字

7 引入进程的目的

  是为了使多道程序并发执行,以提高资源利用率和系统吞吐量。

8 进程间的关系(竞争和协作关系)

  为了解决进程间竞争关系,引入了进程互斥;

为了解决进程间松散的协作关系,引入了进程同步;

为了解决进程间紧密的协作关系,引入了进程通信。

    多个进程之间彼此无关,他们并不知道彼此的存在,并且也不受其他程序的影响。由于这些进程共用了一套计算机系统资源,因而,必然要出现多个进程竞争资源的问题(硬件设备、存储器、处理器和文件等)。

   资源竞争会出现两个控制问题:一个是死锁,另一个是饥饿。解决办法:进程互斥(若干个进程要使用同一个共享资源时,任何时候最多允许一个进程去使用,其他使用该资源的进程必须等待,直到该资源被释放)。

///------线程-------//

1 线程

是指进程中的一个执行流程,一个进程中可以运行多个线程,进程中的多个线程共享进程的内存,线程总是属于某个进程。

2 引入线程的目的

是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。

3 线程基本概念

  ①线程最直接的理解就是“轻量级进程”;

它是一个基本的CPU执行单元,也是程序执行流的最小单元,由线程ID、程序计数器、寄存器集合和堆栈组成;

线程是进程中的一个实体,是被系统独立调度和分派的基本单位;

线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源;

一个线程可以创建和撤销另一个线程;

同一进程中的多个线程之间可以并发执行;

线程也有就绪、阻塞和运行三种基本状态。

4 线程属性

线程是一个轻型实体,它不拥有系统资源,但每个线程都应有一个唯一的标识符和一个线程控制块,线程控制块记录了线程执行的寄存器和栈等现场状态。

不同的线程可以执行相同的程序,即同一个服务程序被不同的用户调用时,操作系统为它们创建成不同的线程。

同一进程中的各个线程共享该进程所拥有的资源。

线程是处理机的独立调度单位,多个线程是可以并发执行的。在单CPU的计算机系统中,各线程可交替地占用CPU;在多CPU的计算机系统中,各线程可同时占用不同的CPU,若各个CPU同时为一个进程内的各线程服务则可缩短进程的处理时间。

—个线程被创建后便开始了它的生命周期,直至终止,线程在生命周期内会经历阻塞态、就绪态和运行态等各种状态变化。

5 线程和进程的比较

调度。

线程是独立调度的基本单位,进程是资源拥有的基本单位。

在同一进程中,线程的切换不会引起进程切换。

在不同进程中进行线程切换,如从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换。
拥有资源。

进程是拥有资源的基本单位,而线程不拥有系统资源(也有一点必不可少的资源),但线程可以访问其隶属进程的系统资源。
并发性。

进程之间可以并发执行,多个线程之间也可以并发执行,使操作系统具有更好的并发性,提高了系统的吞吐量。
系统开销。

a由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、 I/O设备等,因此操作系统所付出的开销远大于创建或撤销线程时的开销。

b在进行进程切换时,涉及当前执行进程CPU环境的保存及新调度到进程CPU环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。

c此外,同一进程内的多个线程共享进程的地址空间,因此,这些线程之间的同步与通信非常容易实现。

地址空间和其他资源(如打开的文件)。

进程的地址空间之间互相独立,同一进程的各线程间共享进程的资源,某进程内的线程对于其他进程不可见。
  
通信方面。

进程间通信(IPC)需要进程同步和互斥手段的辅助,以保证数据的一致性,而线程间可以直接读/写进程数据段(如全局变量)来进行通信。

6 线程同步

  线程同步时为了解决线程并发,可以让同意进程的多个线程互相协调工作,方式有5种。

  原子访问

关键段(临界区):同一进程中,保证某一时候只有一个线程在访问共享数据,如果多个线程试图同时访问临界区,他们会被挂起,直到临界区释放,其他线程才可以继续抢占;

互斥量(内核对象):和临界区相同,也是保证某一时候只有一个线程在访问共享数据,但是他是内核对象,可以在进程间使用;创建互斥量的资源比临界区多,所以如果进程内部使用的话使用临界区会带来速度上的优势,并且能够减少资源占用量。

事件(内核对象):时间是CEvent的对象,也是内核对象,只有当事件有信号时才采取对应的操作,时间分为两类,人工事件和自动事件,默认创建的是自动事件,自动事件:在被至少一个线程释放后自动返回到无信号;手动事件:只有调用SetEvent和ResetEvent才能改变信号状态。(如果某线程必须等待某事件发生后才能存取相应的资源,用事件)

信号量(内核对象):(可以多个线程同时访问共享资源)基于计数原则来限制一次访问共享资源的线程数目,是信号量对象保存当前访问某资源的计数值,如果计数为0,则把类对象放入队列等待,直到超时或技术不为0为止。(适用于一个应用(进程)同时又多个线程存取相应资源)

7 临界区    同步/异步方式    #pragma once

class CMyLock

{

public:

                                          CMyLock()

                                          {

                                                   InitializeCriticalSection(&m_cs);//临界区结构体初始化

                                          }

                                          ~CMyLock()

                                          {

                                                  DeleteCriticalSection(&m_cs);//删除释放临界锁                                    }

private:

                                          CRITICAL_SECTION m_cs;

public:

                                          void Lock()

                                          {

                                                  //EnterCriticalSection(&m_cs);//进入临界区(同步方式)

                                        TryEnterCriticalSection(&m_cs); (异步方式)

                                            }

                                            voidUnLock()

                                            {

                                                      LeaveCriticalSection(&m_cs);//出临界区

                                             }

};

         Lock();

        if( pthis->m_nTicket <= 0 )

        {

            UnLock();

            break;

        }

        str.Format(_T("%d 线程在卖第%d张票"),window,pthis->m_nTicket);

        pthis->m_nTicket--;

        UnLock();

 

 8 互斥量

        HANDLE m_hMutex;

        pthis->m_hMutex = CreateMutex(NULL,TRUE,NULL);

        ReleaseMutex(pthis->m_hMutex );

        WaitForSingleObject( pthis->m_hMutex,INFINITE );

            if( pthis->m_nTicket <= 0 )

            {

                ReleaseMutex(pthis->m_hMutex);

                break;

            }

            str.Format(_T("%d 线程在卖第%d张票"),window,pthis->m_nTicket);

            pthis->m_nTicket--;

        ReleaseMutex(pthis->m_hMutex );

9 线程通信

  全局变量:因为进程中的所有线程都可以访问全局变量,因此可以通过它来通信;

消息:每个线程都有自己的消息队列,可以通过,可以通过postMessage向另外一个线程发送消息,对方通过GetMessage获取,如果GetMessage时发现队列为空,让出时间片,如果队列不为空,处理消息。

事件:用CEvent类的对象来表示,事件只有两种状态:有信号和无信号,线程通过监视信号状态,如果事件有信号,就会在适当的时候进行处理,WaiteForSingleObject()。

10 多线程和线程池的区别

   多线程:需要的时候创建,不需要的时候关掉,每个线程的处理时间都很长;

   线程池:预先创建出一些线程,让他们处于睡眠状态,当任务来临,唤醒线程,开始工作,避免频繁的创建和销毁线程,达到线程对象的重用,另外,使用线程池还可以根据项目灵活的控制并发的数目,适合处理时间短的情况。

/// CPU资源调配方案(CPU调度)///

1  CPU资源调配方案

  一个作业从提交开始直到完成,往往要经历以下三级调度。
1)
作业调度。又称高级调度。

2) 内存调度。又称中级调度。

3) 进程调度。又称为低级调度。

首先,作业调度从外存的后备队列中选择一批作业进入内存,为它们分配内存、输入/输出设备等必要的资源,建立进程,这些进程被送入就绪队列。一般要几分钟。

之后,进程调度从就绪队列中选出一个进程,并把其状态改为运行状态,把CPU分配给它。进程调度的频率很高,一般几十毫秒一次。

系统将那些暂时不能运行的进程调至外存挂起等待。当内存空间宽松时,通过中级调度选择具备运行条件的进程将其唤醒,再重新调入内存,并修改其状态为就绪状态,挂在就绪队列上等待。中级调度是为了提高内存的利用率。中级调度是为了提高内存利用率和系统吞吐量。

 

2 三种调度的关系

1) 作业调度为进程活动做准备,进程调度使进程正常活动起来,中级调度将暂时不能运行的进程挂起,中级调度处于作业调度和进程调度之间。

2) 作业调度次数少,中级调度次数略多,进程调度频率最高。

3) 进程调度是最基本的,不可或缺。

3 进程的调度方式

  进程调度方式是指当某一个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要处理,即有优先权更髙的进程进入就绪队列,此时应如何分配处理机。

  通常有以下两种进程调度方式:
1)
非剥夺调度方式,又称非抢占方式。

是指当一个进程正在处理机上执行时,即使有某个更为重要或紧迫的进程进入就绪队列,仍然让正在执行的进程继续执行,直到该进程完成或发生某种事件而进入阻塞状态时,才把处理机分配给更为重要或紧迫的进程。
 
在非剥夺调度方式下,一旦把CPU分配给一个进程,那么该进程就会保持CPU直到终止或转换到等待状态。这种方式的优点是实现简单、系统开销小,适用于大多数的批处理系统,但它不能用于分时系统和大多数的实时系统。
2) 剥夺调度方式,又称抢占方式。

是指当一个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给这个更为重要或紧迫的进程。
 
釆用剥夺式的调度,对提高系统吞吐率和响应效率都有明显的好处。但“剥夺”不是一种任意性行为,必须遵循一定的原则,主要有:优先权、短进程优先和时间片原则等。

4 操作系统典型的调度算法

  ①先来先服务调度算法(FCFS)

②短作业优先调度算法(SJF)

③优先级调度算法

④高响应比优先调度算法(FCFS)

⑤时间片轮转调度算法(FCFS)

⑥多级反馈队列调度算法(FCFS)

5 作业和进程的关系

批处理系统中作业和进程之间的关系

  作业调度程序,每当选择一道后备作业运行时,首先为该作业创建一个进程,父进程在运行的过程中可以动态的创建一个或者多个子进程,例如,对一条编译语句,该进程可以创建一个子进程执行编译程序对应用户原程序进行编译,子进程也可以继续创建子进程去完成指定的功能,于是一个作业就动态的转换成了一组运行实体—进程族。

  所以批处理系统中会建立很多个用户进程。

分时系统中作业和进程之间的关系

  分时系统的用户通过命令语言逐条地与系统应答式的输入命令,提交作业步。在系统启动时,系统会为每个终端设备建立一个进程(称为终端进程),每输入一条终端命令,可以创建一个子进程去具体执行。

分时系统会创建多个终端进程。

交互的提交批作业

  可以用交互的方式准备好批作业的有关程序、数据及作业控制说明书。

 

///------线程-------//

1 死锁定义:一组进程中的各个进程均占有不会释放的资源,但因互相申请其他进程所占用不会释放的资源而处于一种永久等待状态。

    例如:A进程持有a资源(长期不释放),B进程持有b资源(长期不释放),同时A又想申请b资源,B又想申请a资源,从而在成循环等待。

2 死锁的原因:①系统资源不足

              ②进程运行推进的顺序不合适

              ③资源分配不当

3 满足的4个条件:

①互斥条件:一个资源一次只能被一个进程使用;

例如:资源a b不能被共享,A进程持有a资源,B进程持有b资源;

      ②请求与保持条件:一个进程因请求资源而阻塞时,对已经获得的资源保持不放(别人请求他的资源时也阻塞);

        例如:A进程持有a资源的同时申请b资源,B进程持有b资源的同时申请a资源;

      ③非剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺;

        例如:A进程不能剥夺B进程的b资源,B进程不能剥夺A进程的a资源;

④循环等待条件:若干个进程之间形成一种头尾相接的循环等待资源关系。

     例如:A进程和B进程都要一直等待请求的资源。

4 避免死锁的方法:①按照同一顺序访问对象(避开出现死锁);

                                       ②避免事务中的用户交互

                                       ③减少持有资源的时间

5 怎么发现死锁

   程序中用到死锁的地方,注释部分功能,并分别测试;

   添加printf语句,看看到了哪一条之后就不再printf,就说明死锁了。

 

///

1 消息队列 

  一共有四个函数msgget,msgctl,msgsnd,msgrcv

  ⑴查看消息队列:ipcs

  ⑵删除消息队列:key为0  只能用ipcrm –q msgid

                Key不为0,ipcrm –qmsgid

                                                           ipcrm –Q key

 ⑶消息队列的三个最大值:

MSGMAX  一条消息的数据大小不能超过  cat/proc/sys/kernel/msgmax

MSGMNB  一个消息队列所有数据长度总和不能超过

cat/proc/sys/kernel/msgmnb

MSGMNI   系统中能够创建消息对列的个数cat/proc/sys/kernel/msgmni

  ⑷ msgget创建消息队列:int msgget(key_t key, int msgflg);

                  参数key,是创建队列的键值(消息队列的名字),msgflg是权限(有9个,用法同文件);成功,返回一个非负正数,即该消息队列的标识码,失败返回-1。

           ① msgget(1234, 0664|IPC_CREAT);

Key 1234,msgflg 是0664|IPC_CREAT, 那么,第一次是创建消息队列,第二次是打开消息队列,不会再创建了

② msgget(1234, 0664|IPC_CREAT|IPC_EXCL);

Key 1234,msgflg 是0664|IPC_CREAT|IPC_EXCL那么,第一次是创建消息队列,第二次是还是创建,但是创建失败,因为已经存在

msgget(IPC_PRIVATE, 0664);

如果Key是IPC_PRIVATE,每次都会重新创建出一个不同的消息队列,并且不用加IPC_CREAT|IPC_EXCL

如上图所示:Msgget的执行过程

首先判断是否IPC_PRIVATE?

如果是,说明要创建,则判断是否达到msgmni,如果达到,出错返回(无法创建)(errno=ENOSPC);否则创建;

如果否,判断是否有key?如果没有,判断是否设置IPC_CREAT?如果没设置则无法创建出错返回(errno=ENOENT);如果设置了,判断是否达到msgmni,如果达到,出错返回(无法创建)(errno=ENOSPC);否则创建;

                       如果有key,判断IPC_CREAT|IPC_EXCL是否同时存在,如果同时存在则无法重新创建该key的队列(它已经存在),如果两者不是同时存在,则查看权限是否允许(出啊关键时候没有读,此时有读),如果权限允许,则是打开该key的队列(不是重新创建,kIPC_PRIVATE可以任意重新创建队列),如果权限不允许则出错返回。(errno=EACCES)

⑸ msgctl消息队列的控制函数  

intmsgctl(int msqid,int cmd,structmsqid_ds *buf)

       参数msqid是创建队列的返回值,c

md是将要采取的控制动作(有三个IPC_RMID(可用来删除一个队列,第三个参数为NULL),IPC_STAT(获取消息队列相关的值(查看结构体中各个参数的值),并保存在结构体中(第三个参数)),IPC_SET更改结构体里面的参数(权限等)可借助函数sscanf),

structmsqid_ds *buf是用于传递参数;

成功返回0,失败返回-1。

 

msgctl(msgid,IPC_RMID,NULL);删除名字是msgid的消息队列

msgctl(msgid,IPC_STAT,&buf);输出一些值

       printf("mode=%o\n",buf.msg_perm.mode);      mode=666

       printf("number=%d\n",(int)buf.msg_qnum);

       sscanf("600","%o",(unsignedint)&buf.msg_perm.mode);

       msgctl(msgid,IPC_SET,&buf);更改权限

       printf("mode=%o\n",buf.msg_perm.mode);       mode=600

       其中,sscanf("600","%o",(unsignedint)&buf.msg_perm.mode);把字符串600按照%o的形式,格式化到变量buf.msg_perm.mode中。

⑹msgsnd把一条消息添加到消息队列中

       int msgsnd(int msqid,const void*msgp,size_tmsgsz,int msgflg)

       参数msqidshimsgget函数的返回值;

msgp是一个指针,指向准备发送的消息;

msgsz是准备发送消息的消息长度(不包括消息开始的long),

msgflg控制着当前消息队列满或者达到系统上限时将要发生的事情(可以设置为0,满就交等待),消息必须以一个longint开始。

成功返回0,失败返回-1。

⑺msgrcv从消息队列接收消息

ssize_tmsgrcv(int msqid,void*msgp,size_t msgsz,long msgtype,int msgflg)

参数msqidshimsgget函数的返回值;

msgp是一个指针,指向准备接收的消息;

msgsz是准备接收消息的消息长度(不包括消息开始的long);

msgtype他可以实现接收优先级的简单形式;

       msgtype=0 返回队列第一条消息;

      msgtype> 返回队列第一条类型等于msgtype的消息

      msgtype<0 返回队列第一条类型小于等于msgtype绝对值的消息

      msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误

      msgflg=MSG_NOERROR,消息大小超过msgsz时被截断

      msgflg>0且msgflg=MSC_EXCEPT,接收类型不等于msgflg的第一消息。

msgflg控制着队列中没有相应类型的消息可供接收时将要发生的事

成功返回实际放到接收缓冲区里去的字符个数,失败返回-1。

getopt(argc, argv,”nt:”),解析命令行

2 消息队列实现回射  C/S

用于双向通信,存储客户端和服务器的消息,实现客户端服务器间进程通信。

3  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值