• 领导讲话
  • 自我介绍
  • 党会党课
  • 文秘知识
  • 转正申请
  • 问题清单
  • 动员大会
  • 年终总结
  • 工作总结
  • 思想汇报
  • 实践报告
  • 工作汇报
  • 心得体会
  • 研讨交流
  • 述职报告
  • 工作方案
  • 政府报告
  • 调研报告
  • 自查报告
  • 实验报告
  • 计划规划
  • 申报材料
  • 当前位置: 勤学考试网 > 公文文档 > 工作方案 > 正文

    北邮操作系统消费者与生产者实验报告x

    时间:2020-10-04 16:55:00 来源:勤学考试网 本文已影响 勤学考试网手机站

    操作系统实验课程报告

    课题:消费者与生产者实验

    姓 名 张涛

    学 院 计算机学院

    班 级 2011211311

    学 号 2011211419

    2013年 12月14日

    ( 2) 阅读 Linux 的 pthread.h 源码文件,分析线程的创建过程。

    ( 2) 阅读 Linux 的 pthread.h 源码文件,分析线程的创建过程。

    1.实验目的:

    1) 理解线程同步的思想和方法,学会用线程同步解决临界区问题,本次实验解决生产 者消费者问题

    2 了解 windows 系统或 linux 系统下中信号量的使用方法。

    2.实验预备内容

    (1) 阅读Linux的sched.h源码文件,加深对进程管理概念的理解。

    这个文件长达 2616 行,这里截取第 1221~1548 行抄录在实验报告最后,即结构体 task_struct,地位相当于 PCB。

    下面对几个比较重要的参数,结合本人的了解 以及 网上查阅的资料 做一点解释。

     中括号内的数字为代码行号,下同。

    volatile long state:【1222】进程状态字,表示进程当前的状态(运行、就绪、等待、僵

    死、暂停、交换) ,分别对应已定义好的常量;

    TASK_RUNING :正在运行或可运行状态;

    TASK_INTERRUPTIBLE :可打断睡眠状态; TASK_UNINTERRUPTIBLE :不可打断睡眠状态;

    TASK_ZOMBLE :僵死状态;

    TASK_STOPPED :暂停状态;

    交换状态。

    void *stack:【1223】进程所使用的栈空间;

    unsigned int flags:【 1225】进程标志(创建、关闭、跟踪、被跟踪、内核 dump 等),同

    样对应已定义好的常量;

    unsigned int rt_priority :【 1237】表示本进程的实时优先级;

    const struct sched_class *sched_clas、sstruct sched_entity se:【 1239,1240】分别是调度类和 调度实体,这两个结构包含了用于任务调度的完整的信息(进程信息、调度策略等) ;

    unsigned int po l i cy : 【 1 260】进程的调度策略标志,有三种调度标志:

    SCHED_OTHER :普通进程的调度策略,基于优先权的轮转法; SCHED_FIFO :实时进程的调度策略,基于先进先出的算法;

    SCHED_RR :实时进程的调度策略,基于优先权的轮询法。

    struct list_head tasks:【 1274】任务队列,为一双向循环链表;

    int pdeath_signal:【1282】父进程终止时产生的信号;

    pid_t pid :【1294】进程标识符,操作系统每创建一个新的进程就要为这个新进程分配一 个进程控制块(PCB),系统内核通过pid区分这些进程的;

    struct task_struct *real_parent:【1307】本进程的父进程的 PCB;

    struct list_head children:【1312】本进程的子进程列表;

    struct list_head ptraced: 【1321】本进程正在使用 ptrace 监视的进程列表;

    struct thread_struct thread:【1375】本进程下属的线程集;

    struct signal_struct *signal、 struct sighand_struct *sighand:【 1383,1384】分别是进程运行时 产生的信号以及信号处理模块。

    pthread 接口说明

    #include <pthread.h>

    1、创建

    int pthread_create( pthread_t *tid, const pthread_attr_t *attr, void *(* func) (void *), void *arg ); attr: 线程属性包括:优先级、初始栈大小,是否应该成为一个守护线程。

    缺省设置, NULL

    后面是线程要执行的函数和参数

    成功返回 0

    2、等待一个给定线程终止

    int pthread_join( pthread_t tid, void **status);等待线程结束 critiction 可以在进程中使用, mutex 只可在进程中使用

    statues返回等待线程的返回值

    multiple defi niti on of ' __dso_ha ndle'

    /usr/lib/gcc/i486-linux-gnu/4.4.3/crtbegin.o:(.data+0x0): first defined here

    threadTest: In function '_init':

    (.init+0x0): multiple definition of '_init'

    /usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crti.o:(.init+0x0): first defined here

    /tmp/cchm2SmY.o:(.data+0x0): multiple definition of 'flag' threadTest:(.data+0x8): first defined here /tmp/cchm2SmY.o: In function 'threadMe

    3、 得到自身的 pid

    pthread_t pthread_self(void);

    4、 pthread_detach 函数

    int pthread_detach( pthread_t pid );

    把指定的线程转变为脱离状态

    一个线程或者是可汇合的(joinable,缺省值),或者是脱离的(detached)。当一个可汇 合的线程终止时,它的线程ID和退出状态将留到另一个线程对它调用 pthread_join。脱离线

    程却象守护进程:当它们终止的时, 所有相关资源都被释放, 我们不能等待它们终止。

     如果 一个线程需要知道另一个线程什么时候终止,那就最好好吃第二个线程的可汇合状态。

    本函数通常由想让自己脱离的线程调用,如下语句

    pthread_detach( pthread_self() );

    5、 终止一个线程

    void pthread_exit( void *statue );

    指针sttus不能指向局部于调用对象,因为线程终止时这样的对象也消失

    ( 3) 阅读 Linux 的 semaphore.h 源码文件,分析线程的创建过程。

    typedef struct sem_t_ * sem_t;

    PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,

    int pshared, unsigned int value);

    PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);

    PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);

    PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);

    PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);

    PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,

    int coun t);

    PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);

    PTW32_DLLPORT int __cdecl sem_u nlin k (co nst char * name);

    int sem_init(sem_t *sem,int pshared,unsigned int value。用于信号量的初始化,第一个参数 为信号量的名称,第二个参数为信号量的共享属性,一般设为 0 (不共享),第三个参数为

    信号量的初始值。

    int sem_wait(sem_t *sem)。相当于上面的 wait()操作,作用是当信号量的值大于 0时,给

    信号量的值减1,否则会阻塞直至信号量的值大于 0。它是一个原子操作。

    int sem_post(sem_t *sem)。相当于上面的 signal(操作,作用是给信号量的值加 1。它也是

    一个原子操作。

    ******************************************************************************/

    实验环境

    此实验采用的是 Win8下Microsoft Visual Stdio 2012 工程。由于系统不包含 semaphored,

    sched.h及pthread.h头文件,所以这些头文件都是从网上 FTP资源下载后,加入工程的。

    程序中加入 #pragma comment(lib , "pthreadVC2.lib")来调用 pthread链接库。

    文件根目录下已下载 pthreadVC2.dll ******************************************************************************/

    实验步骤

    A .设计思路

    这个问题是进程同步的经典问题之一,基本思路是设置三个信号量: mutex信号量,用

    于控制生产者和消费者对于缓冲区的互斥访问; empty信号量,记录当前为空的缓冲区的数

    目,初始化为所有缓冲区的数目 BUF_SIZE full信号量,记录当前已满的缓冲区的数目, 初始化为0。

    ******************************************************************************/

    一个buffer,一个生产者,一个消费者

    (1)规则

    只有buffer为空才能put;只有buffer中有数据才能get;不允许多个put操作同时进行; 不允许多个

    get操作同时进行。

    这时buffer变成了临界资源,消费者之间需要互斥地使用,生产者之间也需要互斥地使 用,消费者和生产者之间也需要互斥地使用,这时设置两个信号量

    s1, s2实现同步,例外设置 S信号,代表buffer这种临界资源,用于互斥,称之为互

    L /宀口曰. 斥信号量。

    (2 )实现流程

    <生产者>p (s1)"判断buffer是否空"

    p ( s)

    "是否可进行put,是否有其他进程占用

    buffer"

    putv (s)"释放buffer,让其他进程可以使用 "v (s2)

    "给消费者进程释放一个 buffer中有数据的

    信号”

    <消费者>p( s2)"判断是否有数据”

    p( s)"是否可进行get,是否有其他进程占用”

    getv ( s)"释放buffer,让其他进程可以使用 "v ( s1)

    "给生产者释放一个 buffer为空的信号”通过3个信号量,实现了消费者和生产者之间同

    步关系,也保证了在某个时刻只有一个进程使用临界资源 buffer。

    生产者进程的代码结构描述如下:

    while(true)

    { n extp=produce();wait(empty);wait(mutex);put (n extp);sig nal(mutex);sig nal(full); }

    消费者进程的代码结构描述如下:

    while(true)

    { wait(full);wait(mutex); nextc=get();sig nal(mutex);sig nal(empty);c on sume( nextc); }

    这里两个wait语句的次序并不能调换, 这是因为如果将两个 wait操作即wait( full)和

    wait ( mutex )互换位置,或者将 release( mutex )与release( full )互换位置,当缓冲区存

    满产品时,生产者又生产了一件产品,它欲向缓冲区存放时将在 empty上等待,但它已经

    占有了使用缓冲区的权利。这时消费者要取产品时将停留在 mutex上得不到使用缓冲区的

    权利,导致生产者等待消费者取走产品,而消费者却在等待生产者释放使用缓冲区的权利, 这种相互等待永远结束不了。因此进程将会发生死锁。

    ******************************************************************************I

    B .实验代码分析

    /*

    Producer

    Produce items and try to put it into the buffer

    If the buffer is full, wait ing

    When produced, we output like that: Producer 2 produced 222

    When successfully put, we output: Producer 2 have put product 222 into the buffer after 100 millisec onds

    The milliseconds is the timespan from the producer produced the item

    When the buffer is full but the producer put the item, an error occurred

    (No way it will happe n...)

    */

    #define PTIMESPANMA)5000

    void* producer( void* params)

    {

    int id=*(i nt *)params; while (true)

    {

    SLEEga nd()%PTIMESPANMAX

    buffer item rnd=rand();

    long beg in, end;

    CLOCKbegi n);

    printf("%ld:\t Producer %d\t produced %d\n" , (long)(begin-threadStart), id, rnd);

    sem_wait(&empty);

    pthread_mutex_lock(&mutex);

    (CLOCKS nd), i nsert item(r nd))

    ? printf("%ld:\t Producer %d\t have put %d\t after %d\t milliseconds\n" ,end-threadStart, id, rnd, en d-begi n)

    :printf( "%ld:\t Producer %d\t Report Error!\n" , end-threadStart, id);

    pthread_mutex_u nlock(&mutex);

    sem_post (&full);

    }

    }

    ******************************************************************************/

    消费者:

    /*

    Con sumer

    Try to con sume items from the buffer

    If the buffer is empty, wait ing

    When try to con sume, we output like that: Con sumer 3 want to con sume

    When successfully con sumed, we output: Con sumer 3 con sumed 222 after 100 millisec onds

    The milliseconds is the timespan from the consumer try to consume the item

    When the buffer is empty but the con sumer con sumed the item, an error occurred

    (No way it will happe n...)

    */

    #define CTIMESPANMAX 5000

    void * consumer( void * params)

    {

    int id=*( int *) params ;

    while (true)

    {

    SLEEP(rand()% CTIMESPANMAX);

    long begi n, end;

    CLOCK(begi n);

    pri ntf( "%ld:\t Con sumer %d\t want to con sume\n" , beg in-threadStart, id);

    sem wait(&full);

    pthread_mutex_lock(&mutex);

    buffer_item item=buffer[currentlndex];

    (CLOCK(e nd), remove item(&item))

    ? printf( "%ld:\t Consumer %d\t consumed %d\t after %d\t milliseconds\n"

    SLEEP(1);

    SLEEP(1);

    en d-threadStart, id, item, en d-beg in)

    en d-threadStart, id, item, en d-beg in)

    :printf( "%ld:\t Consumer %d\t Report Error!\n" , end-threadStart, id); pthread_mutex_u nlock(&mutex);

    sem_post(&empty);

    }

    }

    ******************************************************************************/

    主函数:

    int main(int argc, char* argv[])

    {

    sra nd(u nsig ned in t(time(0)));

    //In it mutex, full and empty

    pthread_mutex_init(&mutex, NULL );

    sem init(&full, 0, BUFFER SIZE); sem」n it(&empty, 0, BUFFER_SIZE);

    int i=0;

    // e... No item in the buffer now, so full is "full"

    for(i=0; i< BUFFER_SIZE; i++)

    sem wait(&full);

    int sleepTime=O;

    int producerCou nt=O;

    int con sumerCou nt=O

    pri ntf( "How long to sleep before term in ati ng:");

    scanf s('%d", &sleepTime);

    printf( "The number of producer threads:");

    scanf s('%d", &producerCount);

    printf( "The number of consumer threads:');

    sca nf s('%d", &con sumerCou nt);

    //In it threadStart

    CLOCK (threadStart);

    // Create producer threads

    for(i=0; ivproducerCou nt; i++)

    {

    pthread t pid;

    pthread create(&pid, NULL , producer, (void *)&i);

    SLEEP(1);

    }

    // Create con sumer threads

    for(i=0; i<c on sumerCou nt; i++)

    pthread t pid;

    pthread_create(&pid, NULL , consumer, (void *)&i);

    }

    //Just wait and the n... end

    SLEEP(sleepTime);

    printf( "End of time\n“);

    return 0;

    }

    ****************************************************************************

    C.实验运行结果:

    1?程序初始化格式:

    DMJsers\tao\documents\visual studio 2012\Proj ec ts\Co n so le A ppi i c ati on, ?

    Hlow long to sleep before termiiiatingf: 50000

    The nunbei^ of producer threads: 3

    The numbejr of consuner threads - 3_

    ****************************************************************************

    2?程序运行结果:

    r \ .、八.~ *

    生产者:

    producer 0 1 2

    消费者:

    con sumer 0 1 2

    生产者生产后将数据put到buffer中去

    消费者在申请 mutex (want to consume)后,即可消费。

    42:

    PFoduceF*

    0

    produced

    1846?

    42 :

    Producer

    0

    have put

    18467

    aft Ei'

    G

    nilllseconds

    44:

    Producei*

    1

    produced

    18467

    44;

    Producer

    1

    have put

    1R467

    after

    0

    milliseconds

    16:

    Producei*

    2

    produced

    18467

    4G:

    Producei*

    2

    haue put

    18467

    a( ter

    0

    milliseccnds

    48:

    Consumei*

    0

    want to ii

    48:

    Consumer

    consuned

    18467

    af tei'

    0

    millisecionds

    &0:

    Consunei'

    1

    want to i

    consume

    50:

    Cans unet'

    1

    consuned

    1846?

    af tei*

    B

    milllsecionds

    52 :

    Cansunei'

    2

    Nairit to 耳

    consume

    52:

    2

    consumed

    16467

    after

    0

    rtilliseconds

    1377;

    Producer

    0

    produced

    265Q0

    137?:

    Producei*

    0

    have put

    265U

    after

    e

    nilliseconds

    1379:

    Producei*

    1

    produced

    265QS

    1379 :

    Producer*

    1

    haue put

    af ter

    0

    milliseconds

    1381:

    Producer

    2

    produced

    265W

    1381:

    Produtcei?

    2

    have put

    2£50S

    after1

    s

    nilllseconds

    119S7

    Con^uner

    1

    uant to consume

    11960

    Consumer

    1

    consuned 28145

    after

    1

    billiseconds

    12 977

    Producer

    Q

    produced 16827

    12977

    Producer

    0

    have put 16827

    after

    6

    nilliseconds

    12985

    Producei*

    1

    produced 16827

    12985

    Fs*0>ducEl*

    1

    have put 16827

    after

    e

    nilliseconds

    13 423

    Cun^uiner

    0

    vant to consume

    13423

    Consuner

    Q

    consuned 1682?

    after

    0

    billiseconds

    13438

    Consunei*

    2

    uant to consume

    13438

    Con^uner

    2

    consumed 1G827

    Af ter

    0

    milliseconds

    1343?

    Consumer

    1

    vant to con Slime

    14SH1

    Producer

    2

    produced 16827

    14S01

    Producer

    2

    have put 16827

    after

    P

    nilliseconds

    14502

    Consumer

    1

    consumed 1682?

    after

    1863

    nilllseGonds

    177E2

    Consumer

    0

    want to consume

    17797

    Consumer

    2

    vant to consume

    179-10

    Producer

    0

    produced 491

    1794R

    Producer

    0

    have put 491

    after

    0

    billiseconds

    17940

    Con^uner

    0

    consumed 491

    af ter

    15B

    inillisecond^

    17948

    Produce!'

    1

    produced 491

    17948

    Producer

    1

    have put 491

    after

    Q

    ntilliseconds:

    17948

    Consumer

    2

    consumed 491

    after

    1S1

    milliseconds

    1^862

    Consumer

    1

    uant to consume

    D:\Use rs\ta o\d oc u m e nts\v i su a I studio 20l2\Projects\ConsoleApplication..

    X

    由结果看出,三个消费者和三个生产者一直处于相互互斥工作状态, 并未出现死锁,拥堵等

    异常状态。程序运行成功。

    实验总结

    • 考试时间
    • 范文大全
    • 作文大全
    • 课程
    • 试题
    • 招聘
    • 文档大全

    推荐访问