2222222

#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 ;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值