labweek14

实验报告

实验内容

实验内容:Peterson 算法。

把 Lecture08 示例 alg.8-1~8-3 拓展到多个读线程和多个写线程,应用 Peterson 算法原理设计实现共享内存互斥。

实验环境

 Ubuntu 20.04.2.0(64位)

实验过程

编译运行:
在这里插入图片描述

可以看到主线程创建了5个写进程和5个读进程:
在这里插入图片描述

5个写线程和5个读线程并发执行:
在这里插入图片描述

其中写线程4和读线程4进入临界区对共享内存进行读写操作,其他线程在等待区:
在这里插入图片描述

进行写读操作:
在这里插入图片描述

退出当前的写线程和读线程:

在这里插入图片描述

可以看到,写线程4和读线程2退出了临界区:
在这里插入图片描述

之后写线程2和读线程3分别进入临界区对共享内存进行读写操作:
在这里插入图片描述

进行写读操作:
在这里插入图片描述

退出当前读写线程:
在这里插入图片描述

写线程2和读线程3退出了临界区,写线程3和读线程0进入了临界区:
在这里插入图片描述

继续进行写读操作:
在这里插入图片描述

退出当前读写线程,写线程3和读线程0退出了临界区,写线程1和读线程1离开等待区进入临界区:
在这里插入图片描述

进行读写操作:
在这里插入图片描述

退出当前读写线程,写线程1和读线程1退出了临界区,写线程0和读线程2离开等待区进入临界区:
在这里插入图片描述

进行读写操作:
在这里插入图片描述

退出当前读写线程,写线程0和读线程2退出了临界区,所有线程执行完毕,程序结束:
在这里插入图片描述

从代码的运行情况来看,本次实验成功实现了共享内存互斥的多读写线程。

源代码

  1. alg.8-0-shmdata.h
#define TEXT_SIZE 4 * 1024 /* = PAGE_SIZE, size of each message */

#define TEXT_NUM 1         /* maximal number of mesages */

/* total size can not exceed current shmmax,

       or an 'invalid argument' error occurs when shmget */



/* a demo structure, modified as needed */

struct shared_struct

{

    int written;           /* flag = 0: buffer writable; others: readable */

    char mtext[TEXT_SIZE]; /* buffer for message reading and writing */

};



#define PERM S_IRUSR | S_IWUSR | IPC_CREAT



#define ERR_EXIT(m)         \

    do                      \

    {                       \

        perror(m);          \

        exit(EXIT_FAILURE); \

    } while (0)


  1. alg.8-1-shmcon.c
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/stat.h>

#include <sys/wait.h>

#include <sys/shm.h>

#include <fcntl.h>



#include "alg.8-0-shmdata.h"



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

{

    struct stat fileattr;

    key_t key; /* of type int */

    int shmid; /* shared memory ID */

    void *shmptr;

    struct shared_struct *shared; /* structured shm */

    pid_t childpid1, childpid2;

    char pathname[80], key_str[10], cmd_str[80];

    int shmsize, ret;



    shmsize = TEXT_NUM * sizeof(struct shared_struct);

    printf("max record number = %d, shm size = %d\n", TEXT_NUM, shmsize);



    if (argc < 2)

    {

        printf("Usage: ./a.out pathname\n");

        return EXIT_FAILURE;

    }

    strcpy(pathname, argv[1]);



    if (stat(pathname, &fileattr) == -1)

    {

        ret = creat(pathname, O_RDWR);

        if (ret == -1)

        {

            ERR_EXIT("creat()");

        }

        printf("shared file object created\n");

    }



    key = ftok(pathname, 0x27); /* 0x27 a project ID 0x0001 - 0xffff, 8 least bits used */

    if (key == -1)

    {

        ERR_EXIT("shmcon: ftok()");

    }

    printf("key generated: IPC key = %x\n", key); /* can set any nonzero key without ftok()*/



    shmid = shmget((key_t)key, shmsize, 0666 | PERM);

    if (shmid == -1)

    {

        ERR_EXIT("shmcon: shmget()");

    }

    printf("shmcon: shmid = %d\n", shmid);



    shmptr = shmat(shmid, 0, 0); /* returns the virtual base address mapping to the shared memory, *shmaddr=0 decided by kernel */



    if (shmptr == (void *)-1)

    {

        ERR_EXIT("shmcon: shmat()");

    }

    printf("shmcon: shared Memory attached at %p\n", shmptr);



    shared = (struct shared_struct *)shmptr;

    shared->written = 0;



    sprintf(cmd_str, "ipcs -m | grep '%d'\n", shmid);

    printf("\n------ Shared Memory Segments ------\n");

    system(cmd_str);



    if (shmdt(shmptr) == -1)

    {

        ERR_EXIT("shmcon: shmdt()");

    }



    printf("\n------ Shared Memory Segments ------\n");

    system(cmd_str);



    sprintf(key_str, "%x", key);

    char *argv1[] = {" ", key_str, 0};



    childpid1 = vfork();

    if (childpid1 < 0)

    {

        ERR_EXIT("shmcon: 1st vfork()");

    }

    else if (childpid1 == 0)

    {

        execv("./alg.8-2-shmread.o", argv1); /* call shm_read with IPC key */

    }

    else

    {

        childpid2 = vfork();

        if (childpid2 < 0)

        {

            ERR_EXIT("shmcon: 2nd vfork()");

        }

        else if (childpid2 == 0)

        {

            execv("./alg.8-3-shmwrite.o", argv1); /* call shmwrite with IPC key */

        }

        else

        {

            wait(&childpid1);

            wait(&childpid2);

            /* shmid can be removed by any process knewn the IPC key */

            if (shmctl(shmid, IPC_RMID, 0) == -1)

            {

                ERR_EXIT("shmcon: shmctl(IPC_RMID)");

            }

            else

            {

                printf("shmcon: shmid = %d removed \n", shmid);

                printf("\n------ Shared Memory Segments ------\n");

                system(cmd_str);

                printf("nothing found ...\n");

            }

        }

    }

    exit(EXIT_SUCCESS);

}


  1. alg.8-2-shmread.c
#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/stat.h>

#include <string.h>

#include <sys/shm.h>

#include <pthread.h>

#include <signal.h>



#include "alg.8-0-shmdata.h"



typedef struct

{

    key_t key;

    pthread_t thread_num;

} argu;



static int counter = 0;

/* number of process(s) in the critical section */

int max_num = 5; /* default max thread number */

int level[5];

/* level number of processes 0 .. max_num-1 */

int waiting[4];

/* waiting process of each level number 0 .. max_num-2 */



static void *ftn(void *arg)

{

    void *shmptr = NULL;

    struct shared_struct *shared;

    int shmid;



    argu *argument = (argu *)arg;

    key_t key = (*argument).key;

    int thread_num = (*argument).thread_num;



    int lev, k, j;



    printf("%*sreading thread-%3d, ptid = %lu working\n", 30, " ", thread_num, pthread_self());



    for (lev = 0; lev < max_num - 1; ++lev)

    { /* there are at least max_num-1 waiting rooms */

        level[thread_num] = lev;

        waiting[lev] = thread_num;

        while (waiting[lev] == thread_num)

        { /* busy waiting */

            /*  && (there exists k != thread_num, such that level[k] >= lev)) */

            for (k = 0; k < max_num; k++)

            {

                if (level[k] >= lev && k != thread_num)

                {

                    break;

                }

                if (waiting[lev] != thread_num)

                { /* check again */

                    break;

                }

            } /* if any other proces j with level[j] < lev upgrades its level to or greater than lev during this period, then process thread_num must be kicked out the waiting room and waiting[lev] != thread_num, and then exits the while loop when scheduled */

            if (k == max_num)

            { /* all other processes have level of less than process thread_num */

                break;

            }

        }

    }

    /* critical section of process thread_num */

    printf("%*sreading thread-%3d, ptid = %lu entering the critical section\n", 30, " ", thread_num, pthread_self());

    counter++;

    if (counter > 1)

    {

        printf("ERROR! more than one processes in their critical sections\n");

        kill(getpid(), SIGKILL);

    }



    shmid = shmget((key_t)key, TEXT_NUM * sizeof(struct shared_struct), 0666 | PERM);

    if (shmid == -1)

    {

        ERR_EXIT("shread: shmget()");

    }



    shmptr = shmat(shmid, 0, 0);

    if (shmptr == (void *)-1)

    {

        ERR_EXIT("shread: shmat()");

    }

    printf("%*sshmread: shmid = %d\n", 30, " ", shmid);

    printf("%*sshmread: shared memory attached at %p\n", 30, " ", shmptr);

    printf("%*sshmread thread-%3d ready ...\n", 30, " ", thread_num);



    shared = (struct shared_struct *)shmptr;



    while (1)

    {

        while (shared->written == 0)

        {

            sleep(1); /* message not ready, waiting ... */

        }

        printf("%*sYou wrote: %s\n", 30, " ", shared->mtext);

        shared->written = 0;

        if (strncmp(shared->mtext, "end", 3) == 0)

        {

            break;

        }

    } /* it is not reliable to use shared->written for process synchronization */



    if (shmdt(shmptr) == -1)

    {

        ERR_EXIT("shmread: shmdt()");

    }



    printf("%*sreading thread-%3d, ptid = %lu exit the critical section\n", 30, " ", thread_num, pthread_self());



    counter--;

    /* end of critical section */



    level[thread_num] = -1;

    /* allow other process of level max_num-2 to exit the while loop 

         and enter his critical section */

    pthread_exit(0);

}



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

{

    key_t key;

    sscanf(argv[1], "%x", &key);

    printf("%*sshmread: IPC key = %x\n", 30, " ", key);



    memset(level, (-1), sizeof(level));

    memset(waiting, (-1), sizeof(waiting));



    int i, ret;

    pthread_t ptid[max_num];

    argu argument[max_num];



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

    {

        argument[i].key = key;

        argument[i].thread_num = i;

    }



    printf("%*sreading thread number = %d\n", 30, " ", max_num);

    printf("%*sreading main(): pid = %d, ptid = %lu.\n", 30, " ", getpid(), pthread_self());



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

    {

        ret = pthread_create(&ptid[i], NULL, &ftn, (void *)&argument[i]);

        if (ret != 0)

        {

            fprintf(stderr, "pthread_create error: %s\n", strerror(ret));

        }

    }



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

    {

        ret = pthread_join(ptid[i], NULL);

        if (ret != 0)

        {

            perror("pthread_join()");

        }

    }



    return 0;

}
  1. alg.8-3-shmwrite.c
#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/stat.h>

#include <string.h>

#include <sys/shm.h>

#include <pthread.h>

#include <signal.h>



#include "alg.8-0-shmdata.h"



typedef struct

{

    key_t key;

    pthread_t thread_num;

} argu;



// #define MAX_N 1024



static int counter = 0;

/* number of process(s) in the critical section */

int max_num = 5; /* default max thread number */

int level[5];

/* level number of processes 0 .. max_num-1 */

int waiting[4];

/* waiting process of each level number 0 .. max_num-2 */



static void *ftn(void *arg)

{

    void *shmptr = NULL;

    struct shared_struct *shared;

    int shmid;

    char buffer[BUFSIZ + 1]; /* 8192bytes, saved from stdin */



    argu *argument = (argu *)arg;

    key_t key = (*argument).key;

    int thread_num = (*argument).thread_num;



    int lev, k, j;



    printf("writing thread-%3d, ptid = %lu working\n", thread_num, pthread_self());



    for (lev = 0; lev < max_num - 1; ++lev)

    { /* there are at least max_num-1 waiting rooms */

        level[thread_num] = lev;

        waiting[lev] = thread_num;

        while (waiting[lev] == thread_num)

        { /* busy waiting */

            /*  && (there exists k != thread_num, such that level[k] >= lev)) */

            for (k = 0; k < max_num; k++)

            {

                if (level[k] >= lev && k != thread_num)

                {

                    break;

                }

                if (waiting[lev] != thread_num)

                { /* check again */

                    break;

                }

            } /* if any other proces j with level[j] < lev upgrades its level to or greater than lev during this period, then process thread_num must be kicked out the waiting room and waiting[lev] != thread_num, and then exits the while loop when scheduled */

            if (k == max_num)

            { /* all other processes have level of less than process thread_num */

                break;

            }

        }

    }

    /* critical section of process thread_num */

    printf("writing thread-%3d, ptid = %lu entering the critical section\n", thread_num, pthread_self());

    counter++;

    if (counter > 1)

    {

        printf("ERROR! more than one processes in their critical sections\n");

        kill(getpid(), SIGKILL);

    }



    shmid = shmget((key_t)key, TEXT_NUM * sizeof(struct shared_struct), 0666 | PERM);

    if (shmid == -1)

    {

        ERR_EXIT("shmwite: shmget()");

    }



    shmptr = shmat(shmid, 0, 0);

    if (shmptr == (void *)-1)

    {

        ERR_EXIT("shmwrite: shmat()");

    }

    printf("shmwrite: shmid = %d\n", shmid);

    printf("shmwrite: shared memory attached at %p\n", shmptr);

    printf("shmwrite thread-%3d ready ...\n", thread_num);



    shared = (struct shared_struct *)shmptr;



    while (1)

    {

        while (shared->written == 1)

        {

            sleep(1); /* message not read yet, waiting ... */

        }



        printf("Enter some text: ");

        fgets(buffer, BUFSIZ, stdin);

        strncpy(shared->mtext, buffer, TEXT_SIZE);

        printf("shared buffer: %s\n", shared->mtext);

        shared->written = 1; /* message prepared */



        if (strncmp(buffer, "end", 3) == 0)

        {

            break;

        }

    }

    /* detach the shared memory */

    if (shmdt(shmptr) == -1)

    {

        ERR_EXIT("shmwrite: shmdt()");

    }



    printf("writing thread-%3d, ptid = %lu exit the critical section\n", thread_num, pthread_self());



    counter--;

    /* end of critical section */



    level[thread_num] = -1;

    /* allow other process of level max_num-2 to exit the while loop 

         and enter his critical section */

    pthread_exit(0);

}



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

{

    key_t key;

    sscanf(argv[1], "%x", &key);

    printf("%*sshmread: IPC key = %x\n", 30, " ", key);



    memset(level, (-1), sizeof(level));

    memset(waiting, (-1), sizeof(waiting));



    int i, ret;

    pthread_t ptid[max_num];

    argu argument[max_num];



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

    {

        argument[i].key = key;

        argument[i].thread_num = i;

    }



    printf("writing thread number = %d\n", max_num);

    printf("writing main(): pid = %d, ptid = %lu.\n", getpid(), pthread_self());



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

    {

        ret = pthread_create(&ptid[i], NULL, &ftn, (void *)&argument[i]);

        if (ret != 0)

        {

            fprintf(stderr, "pthread_create error: %s\n", strerror(ret));

        }

    }



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

    {

        ret = pthread_join(ptid[i], NULL);

        if (ret != 0)

        {

            perror("pthread_join()");

        }

    }



    return 0;

}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的高校科研信息管理系统实现了操作日志管理、字典管理、反馈管理、公告管理、科研成果管理、科研项目管理、通知管理、学术活动管理、学院部门管理、科研人员管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让高校科研信息管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值