2133213

#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include<time.h>
#include <sys/sem.h>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include <queue>
#include <stdlib.h>
#include <pthread.h>
#include <stack>
#include <sys/types.h>
#include <sys/ipc.h>
#include "../header/header.h"
#include <sys/shm.h>
using namespace std;
pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER;

union semun {
 
        int val; /* value for SETVAL */
 
        struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
 
        unsigned short *array; /* array for GETALL, SETALL */
 
        struct seminfo *__buf; /* buffer for IPC_INFO */
 
        };
class Task{
private:
    string name;
    double size;
    int priority;
public:
    bool operator<(const Task& task) const{
        if(this->priority == task.priority){
            return this->size > task.size;
        }
        else{
            return this->priority > task.priority;
        }
    }

    Task(const string &name, double size, int priority) : name(name), size(size), priority(priority) {}

    const string &getName() const {
        return name;
    }

    void setName(const string &name) {
        Task::name = name;
    }

    double getSize() const {
        return size;
    }

    void setSize(double size) {
        Task::size = size;
    }

    int getPriority() const {
        return priority;
    }

    Task() {
        this->priority = 0;
        this->size = 0;
        this->name = "";
    }

    void setPriority(int prior) {
        Task::priority = prior;
    }
};
class PrintQueue{
public:
    void push(Task task){
        this->printqueue.push(task);
    }
    Task top(){
        return this->printqueue.top();
    }
    void pop(){
        this->printqueue.pop();
    }
    size_t size(){
        return this->printqueue.size();
    }
    bool empty(){
        return this->printqueue.size() == 0;
    }
private:
    priority_queue<Task> printqueue;
};
int key;
int semid;
union semun arg;
int flag ;
PrintQueue printQueue;
int ret;
int print_ret;

/***对信号量数组semnum编号的信号量做P操作***/
int P(int semid, int semnum)
{
    struct sembuf sops={semnum,-1, SEM_UNDO};
    return (semop(semid,&sops,1));
}


/***对信号量数组semnum编号的信号量做V操作***/
int V(int semid, int semnum)
 
{
 
    struct sembuf sops={semnum,+1, SEM_UNDO}; // semundo避免造成死锁

    return (semop(semid,&sops,1));
 
}
void InsertTask(PrintQueue* printque,Task& task){
    if(pthread_mutex_lock(&mutx) != 0)
    {
        perror("pthread_mutex_lock");
        exit(EXIT_FAILURE);
    }
    // 加锁成功
    if (P(semid, 0) < 0)
    {
        perror("P operate error,资源未上锁") ;
        return;
    }
    cout << "获取锁了,正在进行插入" << endl;
    printque->push(task);
    sleep(5);
    cout << "释放" << endl;
    if(pthread_mutex_unlock(&mutx) != 0)
    {
        perror("pthread_mutex_unlock");
        exit(EXIT_FAILURE);
    }
    //退锁
    if (V(semid, 0) < 0)
    {
        perror("P operate error,资源未释放") ;
        return;
    }
}

// 删除打印任务,同时必须使其他试图执行打印以及添加任务的线程阻塞
void delete_task(PrintQueue* que,string name){
    if (P(semid, 0) < 0)
    {
        perror("P operate error,其他进程未休眠");
        return;
    }
    if(pthread_mutex_lock(&mutx) != 0)
    {
        perror("pthread_mutex_lock");
        exit(EXIT_FAILURE);
    }
    PrintQueue* temp_queue;
    bool if_found = false;
    cout << "正在删除名称为" << name << "的打印任务" << endl;
    for (size_t i = 0; i < que->size(); ++i) {
        if(que->top().getName() == name)
        {
            if_found = true;
            que->pop();
            break;
        }
        temp_queue->push(printQueue.top());
        que->pop();
    }
    if(!temp_queue->empty())
    {
        que->push(temp_queue->top());
        temp_queue->pop();
    }
    if(!if_found)
    {
        cout << "未找到对应的打印任务"<<endl;
    }
    if(pthread_mutex_unlock(&mutx) != 0)
    {
        perror("pthread_mutex_unlock");
        exit(EXIT_FAILURE);
    }
    if (V(semid, 0) < 0)
    {
        perror("V operate error,其他进程未唤醒") ;
        return ;
    }
    
}

void  DoPrint(PrintQueue* que){
    if (P(semid, 0) < 0)
    {
        perror("P operate error,其他进程未休眠") ;
        return ;
    }
    if(pthread_mutex_lock(&mutx) != 0)
    {
        perror("pthread_mutex_lock");
        exit(EXIT_FAILURE);
    }
    
    Task task = que->top();
    cout << "正在打印" << task.getName() << "的内容," << "大小为" << task.getSize() << "KB" << endl;
    cout << "[";
    auto t1 = clock();
    for(int i=0;i<100;i++)
    {
        sleep(0.01);
        cout << (char)0xa8 << (char)0x80;
    }
    auto t2 = clock();
    cout << "] 100%" <<endl;
    cout << "打印耗时" << (t2 - t1) / 1000 << "s"<< endl;
    que->pop();
    if (V(semid, 0) < 0)
    {
        perror("P operate error,其他进程未唤醒") ;
        return ;
    }
    if(pthread_mutex_unlock(&mutx) != 0)
    {
        perror("pthread_mutex_unlock");
        exit(EXIT_FAILURE);
    }
    //释放锁
}
void Print_Ongoing_Task(PrintQueue* que){
    if (P(semid, 0) < 0)
    {
        perror("P operate error,其他进程未休眠") ;
        return ;
    }
    if(pthread_mutex_lock(&mutx) != 0)
    {
        perror("pthread_mutex_lock failed");
        exit(EXIT_FAILURE);
    }
    PrintQueue* temp_queue;
    size_t size = que->size();
    for (int i = 0; i < size; ++i) {
        printf("第%d个打印任务是%s,大小为%f,优先级为%d",i,que->top().getName().c_str(),que->top().getSize(),que->top().getPriority());
        temp_queue->push(que->top());
        sleep(1);
        cout << "打印完成!" << endl;
        que->pop();
    }
    que = temp_queue;
    if(pthread_mutex_unlock(&mutx) != 0)
    {
        perror("pthread_mutex_unlock failed");
        exit(EXIT_FAILURE);
    }
     if (V(semid, 0) < 0)
    {
        perror("P operate error,其他进程未唤醒") ;
        return ;
    }
}

int main(int argc, char **argv)
 
{
    struct sembuf semop;
    key = ftok("/tmp", 0x66 ) ;
    if ( key < 0 )
    {
        perror("ftok key error") ;
        return -1 ;
    }

    /***本程序创建了三个信号量,实际使用时只用了一个0号信号量***/
    semid = semget(key,3,IPC_CREAT|0600);

    if (semid == -1)
    {
        perror("create semget error");
        return 0;
    }

    if ( argc == 1 )
    {
        arg.val = 1;
        /***对0号信号量设置初始值***/
        ret =semctl(semid,0,SETVAL,arg);
        if (ret < 0 )
        {
            perror("ctl sem error");
            semctl(semid,0,IPC_RMID,arg);
            return -1 ;
        }
    }
    cout << "程序初始化: ";
    system("date");
    string name;;
    double size;
    int prior;
    Task task;
    pid_t pid;
    key_t  key_n ;
    int shm_id;
    void *shm = NULL;
    char buf[1024+1];
    PrintQueue* que;
    if((key_n = ftok("/",'s')<0))  //生成共享内存的key值
    {
        perror("Fail to ftok");
        exit(EXIT_SUCCESS);
    }
    printf("key num:%d\n",key_n);
 
    if((shm_id = shmget(key_n,1024,0666|IPC_CREAT))==-1)  //创建共享内存
    {
        perror("Fail to shmget");
        exit(EXIT_SUCCESS);
    }
    while(true){
        cout << "请输入你要进行的操作: 1:新增打印任务; 2: 删除打印任务; 3:查看打印任务完成情况 ;4: 开始打印; 0: 退出程序"<< endl;
        int cmd;
        cin >> cmd;
        switch (cmd) {
            case 1:
                cout << "请输入名字"<<endl;
                cin >>name;
                cout <<"请输入大小"<<endl;
                cin >> size;
                cout << "请输入优先级"<< endl;
                cin >>prior;
                task = Task(name,size,prior);
                pid = fork();
                if(pid < 0)
                {
                    perror("fork"); //错误处理
                    exit(1);
                }
                else if(pid == 0)
                {
                    shm = shmat(shm_id,0,0);
                    if(shm==(void *)-1)
                    {
                        perror("Fail to shmat");
                        exit(EXIT_SUCCESS);
                    }
                    que = (PrintQueue*) shm;
                    
                    InsertTask(que,task);
                    exit(0);
                }
                else
                {
                    int status = 0;
                    pid_t res = waitpid(pid, &status, 0); //阻塞式等待
                    if(res > 0) //等待子进程运行成功
                    {
                        printf("\n");
                        printf("插入程序运行结果 Running Code: %d \n", WEXITSTATUS(status));
                        
                    }
                }
                break;
            case 2:
                cout <<"请输入你要删除的打印任务的名称" <<endl;
                cin >> name;
                pid = fork();
                if(pid < 0)
                {
                    perror("fork"); //错误处理
                    exit(1);
                }
                else if(pid == 0)
                {
                    shm = shmat(shm_id,0,0);
                    if(shm==(void *)-1)
                    {
                        perror("Fail to shmat");
                        exit(EXIT_SUCCESS);
                    }
                    que = (PrintQueue*) shm;
                    
                   delete_task(que,name);
                   exit(1);
                }
                else
                {
                    int status = 0;
                    pid_t res = waitpid(-1, &status, 0); //阻塞式等待
                    if(res > 0) //等待子进程运行成功
                    {
                        printf("\n");
                        printf("删除程序运行结果 Running Code: %d \n", WEXITSTATUS(status));
                    }
                }
                break;
            case 3:
                pid = fork();
                if(pid < 0)
                {
                    perror("fork"); //错误处理
                    exit(2);
                }
                else if(pid == 0)
                {
                    shm = shmat(shm_id,0,0);
                    if(shm==(void *)-1)
                    {
                        perror("Fail to shmat");
                        exit(EXIT_SUCCESS);
                    }
                    que = (PrintQueue*) shm;
                   Print_Ongoing_Task(que);
                   return 1;
                }
                else
                {
                    int status = 0;
                    pid_t res = waitpid(-1, &status, 0); //阻塞式等待
                    if(res > 0) //等待子进程运行成功
                    {
                        printf("\n");
                        printf("观察打印队列程序运行结果 Running Code: %d \n", WEXITSTATUS(status));
                    }
                }
                break;
            case 4:
                pid = fork();
                if(pid < 0)
                {
                    perror("fork"); //错误处理
                    exit(1);
                }
                else if(pid == 0)
                {
                    shm = shmat(shm_id,0,0);
                    if(shm==(void *)-1)
                    {
                        perror("Fail to shmat");
                        exit(EXIT_SUCCESS);
                    }
                    que = (PrintQueue*) shm;
                   DoPrint(que);
                   exit(3);
                }
                else
                {
                    int status = 0;
                    pid_t res = waitpid(-1, &status, 0); //阻塞式等待
                    if(res > 0) //等待子进程运行成功
                    {
                        printf("\n");
                        printf("打印程序运行结果 Running Code: %d \n", WEXITSTATUS(status));
                    }
                }
                break;
            case 0:
                exit(0);
                break;
            default:
                break;
        }
    }
    if ( argc >1 )
    {
        semctl(semid,0,IPC_RMID,arg); //删除信号量集合
    }
    return 0 ;
 
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值