labweek7

实验报告

实验内容

 进程间通信—共享内存。实现一个带有 n 个单元的线性表的并发维护。

  1. 建立一个足够大的共享内存空间 (lock, M),逻辑值 lock 用来保证同一时间只有一个进程进入 M;测试你的系统上 M 的上限。
  2. 设计一个程序在 M 上建立一个结点信息结构为 (flag, 学号, 姓名) 的静态链表 L,逻辑值 flag 用作结点的删除标识;在 L 上建立一个以学号为关键字的二元小顶堆,自行设计控制结构 (如静态指针数据域)。
  3. 设计一个程序对上述堆结构的结点实现插入、删除、修改、查找、重排等操作。该程序的进程可以在多个终端并发执行。
  4. 思考:使用逻辑值 lock 实现的并发机制不能解决条件冲突问题。

实验环境

 Ubuntu 20.04.2.0(64位)

实验过程

一. 测试本机共享内存空间的上限

  1. 通过 ipcs -l 可以直接显示本机共享内存的限制,为18014398509465599kbytes,但显然实际用时不可能有这么大的空间可用。

在这里插入图片描述

  1. 编写代码进行测试

设计思路: 改边共享内存的大小,每次创建更大空间的共享内存。

每次内存大小乘2,当共享内存大小超过7085490176时再乘以2将超出可申请内存的大小。
在这里插入图片描述

二. 程序实现

(一)整个程序分为三个部分:

  1. labweek7.h: 头文件,包含各种结构体和说明。
  2. labweek7.c: 控制台,用于最开始创建共享内存和最后删除共享内存。
  3. labweek7-0.c: 进行实际操作(小顶堆)和通信的程序。

(二)演示

  1. 先运行控制台,创建共享内存,同时初始化lock。

在这里插入图片描述
2. 运行两个 labweek7-0.c 程序

在这里插入图片描述

输入一个任意数,第一个可以继续往下运行,第二个被卡住无法继续运行。

在这里插入图片描述

在这里插入图片描述

  1. 演示:

①pop: 先在第一个进程中执行,空堆提示。

在这里插入图片描述

②insert: 插入三个学生。

在这里插入图片描述

③stop: 暂停执行该进程,同时另一个进程继续往下执行。

在这里插入图片描述

在这里插入图片描述

④pop: 输出学号最小的同学的信息同时将他从堆中删除。

在这里插入图片描述

⑤insert: 再插入4个学生。

在这里插入图片描述

⑥search: 查找19335266的学生,未找到;再查找19335278的学生,找到并输出。

在这里插入图片描述

⑦stop: 暂停执行该进程,回到另一个进程继续往下执行。

在这里插入图片描述

在这里插入图片描述

⑧change: 修改学号最小的学生的信息并重排。

在这里插入图片描述

⑨pop: pop直到堆空,刚好6个学生,且按学号从小到大输出。

在这里插入图片描述

⑩quit: 该进程退出,另一个进程继续执行,之后也退出,最后控制台也退出。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

三. 思考

lock不能协调多进程之间的条件冲突问题。

四. 代码

  1. labweek7.h
#define NameSize  21/* = PAGE_SIZE, size of each message */
#define LinkSize 100      /* maximal number of static link */
    /* total size can not exceed current shmmax,
       or an 'invalid argument' error occurs when shmget */


typedef struct{
    int flag;
    unsigned int id;   /* student's id*/
    char name[NameSize];      /* student's name*/
}Link;

/* a demo structure, modified as needed */
struct shared_struct {
    int lock; /* lock = 0: labweek7-0 run; lock = 1: labweek7-1 run; lock = -1: quit*/
    Link link[LinkSize+1]; /* static link: from 1 to LinkSize*/
    int count;  /* the counter of array*/
};

#define PERM S_IRUSR|S_IWUSR|IPC_CREAT

#define ERR_EXIT(m) \
 do { \
 	perror(m); \
 	exit(EXIT_FAILURE); \
 } while(0)
  1. labweek7.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 "labweek7.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 = /*LinkSize**/sizeof(struct shared_struct);
    printf("max record number = %d, shm size = %d\n", LinkSize, shmsize);

    if(argc <2) {
        printf("Usage: ./a.out pathname\n");
        return EXIT_FAILURE;
    }
    // sscanf(argv[1], "%x", &key);
    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->lock = 0;
    shared->count = 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);

    while(1){
        int num;

        printf("Enter number(0: run; -1: quit)\n");
        scanf("%d", &num);

        if(num == -1){
            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"); 
            }
            break;
        }
    }        
    exit(EXIT_SUCCESS);
}
  1. labweek7-0.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/shm.h>

#include "labweek7.h"

void push(Link *link, int i);
void change(Link *minHeap, int n);

int main(int argc, char *argv[])
{
    void *shmptr = NULL;
    struct shared_struct *shared;
    int shmid;
    key_t key;
 
    key = ftok(argv[1], 0x27);
    // sscanf(argv[1], "%x", &key);
    printf("labweek7-0: IPC key = %x\n", key);
    
    shmid = shmget((key_t)key, /*LinkSize**/sizeof(struct shared_struct), 0666|PERM);
    if (shmid == -1) {
        ERR_EXIT("labweek7-0: shmget()");
    }

    shmptr = shmat(shmid, 0, 0);
    if(shmptr == (void *)-1) {
        ERR_EXIT("labweek7-0: shmat()");
    }
    printf("labweek7-0: shmid = %d\n", shmid);
    printf("labweek7-0: shmsize = %ld\n", sizeof(struct shared_struct));    
    printf("labweek7-0: shared memory attached at %p\n", shmptr);
    printf("labweek7-0 process ready ...\n");
    
    shared = (struct shared_struct *)shmptr;
    // shared->count = 0;
    // shared->lock = 0;
    
    while (1) {
            
            // if(shared->lock == 0){
                int r;
                printf("If you want to continue this program, enter a random number:\n");
                
                scanf("%d", &r);
            // }

            while(shared->lock == 1){
                sleep(1);
            }

            shared->lock = 1;

            while(1){
                int ope;
                printf("Enter operation(0: insert; 1: put the first node and delete; 2: change the first node; 3: search; 4: stop; 5: quit)\n");
                
                scanf("%d", &ope);

                if(ope == 0){
                    if(shared->count == LinkSize){
                        printf("The heap is full!\n");
                    }
                    else{ 
                        shared->count++;

                        printf("Enter the student's information(ID and name): \n");
                        
                        scanf("%u", &shared->link[shared->count].id);
                        getchar();
                        fgets(shared->link[shared->count].name, NameSize, stdin);
                        printf("Insert a student: %u %s\n", shared->link[shared->count].id, shared->link[shared->count].name);

                        push(shared->link, shared->count);
                       
                    }
                } 
                else if(ope == 1){
                    if(shared->count == 0){
                        printf("The heap is empty!\n");
                    }
                    else{
                        printf("The first student(node): %u %s\n", shared->link[1].id, shared->link[1].name);

                        shared->link[1] = shared->link[shared->count--];
                        change(shared->link, shared->count);

                        printf("This student delete!\n");
                    }
                }
                else if(ope == 2){
                    if(shared->count == 0){
                        printf("The heap is empty!\n");
                    }
                    else{
                        printf("Enter the student's information that you want to change(ID and name): \n");
                        
                        scanf("%u", &shared->link[1].id);
                        getchar();
                        fgets(shared->link[1].name, NameSize, stdin);
                        printf("Change the first student(node): %u %s\n", shared->link[1].id, shared->link[1].name);

                        change(shared->link, shared->count);

                        printf("This student change!\n");
                    }
                }
                else if(ope == 3){
                    unsigned int ID;
                    int c = 1;
                    printf("Enter the student's id that you want to search: \n");
                    
                    scanf("%u", &ID);

                    while(c <= shared->count){
                        if(ID == shared->link[c].id){
                            printf("The student is: %d %s\n", shared->link[c].id, shared->link[c].name);
                            break;
                        }

                        c++;
                    }

                    if(c == shared->count + 1){
                        printf("This student is not exist!\n");
                    }
                }
                else if(ope == 4){
                    shared->lock = 0;
                    break;
                }
                else if(ope == 5){
                    shared->lock = -1;
                    break;
                }
                else {
                    printf("Invalid input.\n");
                    continue;
                }
            }
            
            if(shared->lock == -1){
                // shared->lock = 1;
                break;
            }

            
    } /* it is not reliable to use shared->written for process synchronization */
     
    if (shmdt(shmptr) == -1) {
        ERR_EXIT("shmcon: shmdt(IPC_RMID)");
    }
 
    // sleep(1);
    exit(EXIT_SUCCESS);
}

void push(Link *link, int i)
{
    while((i>>1) >= 1 && link[i].id < link[i>>1].id){
        Link t = link[i];
        link[i] = link[i>>1];
        link[i>>1] = t;
        i = i>>1;
    }
}

void change(Link *minHeap, int n)
{
    // int a = minHeap[1];
    // minHeap[1] = minHeap[n+1];
    int i = 1;
    while((i<<1) <= n){
        if((i<<1)+1 > n){
            if(minHeap[i].id > minHeap[(i<<1)].id){
                Link t = minHeap[i];
                minHeap[i] = minHeap[(i<<1)];
                minHeap[(i<<1)] = t;
                i = (i<<1);
            }else{
                break;
            }
        }else{
            if((minHeap[i].id > minHeap[(i<<1)].id && minHeap[i].id <= minHeap[(i<<1) + 1].id) || (minHeap[i].id > minHeap[(i<<1)].id && minHeap[i].id > minHeap[(i<<1) + 1].id && minHeap[(i<<1)].id < minHeap[(i<<1) + 1].id)){
                
                Link t = minHeap[i];
                minHeap[i] = minHeap[(i<<1)];
                minHeap[(i<<1)] = t;
                i = (i<<1);
            }else if((minHeap[i].id <= minHeap[(i<<1)].id && minHeap[i].id > minHeap[(i<<1) + 1].id) || (minHeap[i].id > minHeap[(i<<1)].id && minHeap[i].id > minHeap[(i<<1) + 1].id && minHeap[(i<<1)].id >= minHeap[(i<<1) + 1].id)){
                
                Link t = minHeap[i];
                minHeap[i] = minHeap[(i<<1) + 1];
                minHeap[(i<<1) + 1] = t;
                i = (i<<1) + 1;
            }else{
                break;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值