併發任務的可視化

一、任務要求:

linux系統中設計一個父進程,三個子進程(A,B,C)。子進程A,B同時被父進程啓動來計算(不實現具體的計算任務,先用CPU空跑來代替)。進程A計算5分鐘,而進程B計算8分鐘。當進程A,B都計算完成後才能啓動進程C,進程C計算3分鐘。自己尋找前端的可視化方案,當進程在併發計算時,打開網頁能夠看到,那個進程當前正在計算,並且要可視化的顯示計算的進度,還要看出各個進程之間的約束關係。

二、解答思路:

1.父進程fork出子進程A,B。A,B同時執行。進程A B內執行循環空跑CPU,利用gettimeofday()函數獲取時間來控制執行時間。

2.定義全局變量標誌進程A B狀態,初始化爲假,若A B執行完畢後,則子進程A B向主進程發送信號,主進程收到子進程A B完成的信號後調用相應函數改變表示A B狀態的變量爲真,當A B都完成後 ,主進程fork出子進程C,子進程的運行方法同進程A B。

3.可視化:利用瀏覽器進行可視化顯示,則主進程爲服務器,主進程通過管道與進程A B C進行通信,獲取進程運行進度,通過瀏覽器發出請求,主進程收到請求後向瀏覽器發送進程運行情況。網頁通過自動刷新不斷更新數據。

三、代碼:

 


#include <sys/socket.h>

#include <sys/un.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <string.h>

#include <stdio.h>

#include <stdio.h>

#include <signal.h>

#include <stdlib.h>

#include <sys/time.h>

#define TRUE 0x01  

#define FALSE 0x00

#define MAX 10

#define PORT 8080

char flagA=FALSE; //進程A完成標誌

char flagB=FALSE; //進程B完成標誌

int flagC=1; //進程C完成標誌 1:未開始 2:已開始 3:已結束

int flagCount=0; //進程C建立標誌

//進程A信號處理

void endofA(int sig)

{

if(sig==SIGUSR1)

{

flagA=TRUE;

printf("修改了A\n");

}

return;

}

//進程B信號處理

void endofB(int sig)

{

if(sig==SIGUSR2)

{

flagB=TRUE;

printf("修改了B\n");

}

return;

}

//進程C信號處理

void endofC(int sig)

{

if(sig==SIGINT)

{

flagB=3;

printf("修改了C\n");

}

return;

}

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

{

int fdA[2],n; //父進程與A進程通信管道

char stateA[50]="子進程A執行中";

char stateB[50]="子進程B執行中";

char stateC[50]="子進程B執行中";

char temp[5];

pipe(fdA);

int fdB[2];  //父進程與B進程通信管道

pipe(fdB);

int server_socket = socket(AF_INET, SOCK_STREAM, 0);   //服務器socket

struct sockaddr_in server_addr; //服務器地址

memset(&server_addr, 0, sizeof(server_addr)); //清空服務器地址

server_addr.sin_family = AF_INET; //IPv4 網絡協議的套接字類型

server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

server_addr.sin_port = htons(PORT);

bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));

pid_t pidA;

if((pidA=fork())<0)

printf("forkA fail");

if(pidA==0) //進程A

{

close(fdA[0]);

int runtime;

struct timeval start,end;

n=gettimeofday(&start, NULL);

gettimeofday(&end, NULL);

//空跑300秒,每3秒向管道內寫入已運行時間

//採用網頁顯示,主進程與A之間有480個像素,故速度爲1.6

while((runtime=(end.tv_sec-start.tv_sec))<=300)

{

sleep(3);

char timeA[20]={0};

double distanceA=1.6*runtime;

sprintf(timeA,"%.2f",distanceA);

gettimeofday(&end, NULL);  

write(fdA[1],timeA,sizeof(timeA));

}

//向父進程發送信號

if(kill(getppid(),SIGUSR1)==-1)

{

printf("process A send fail");

exit(0);

}

}

else

{

pid_t pidB;

pidB=fork();

//B進程

if(pidB==0)

{

close(fdB[0]);

int runtimeB=0;

float distanceB=0;

struct timeval startB,endB;

n=gettimeofday(&startB, NULL);

gettimeofday(&endB, NULL);

//空跑480秒,每3秒向管道內寫入已運行時間

//採用網頁顯示,主進程與A之間有480個像素,故速度爲1

while((runtimeB=(endB.tv_sec-startB.tv_sec))<=480)

{

sleep(3);

char timeB[20]={0};

distanceB=1*runtimeB;

sprintf(timeB,"%.2f",distanceB);

gettimeofday(&endB, NULL);  

write(fdB[1],timeB,sizeof(timeB));

}

//向父進程發送信號

if(kill(getppid(),SIGUSR2)==-1)

{

printf("process B send fail");

exit(0);

}

}

else

{

close(fdA[1]);

close(fdB[1]);

signal(SIGUSR1,endofA);

signal(SIGUSR2,endofB);

signal(SIGINT,endofC);


while(1)

{

int fdC[2];

close(fdC[1]);

//判斷AB是否運行完畢

if(flagA==TRUE&&flagB==TRUE&&flagC!=3&&flagCount==0)

{

flagC=2;

pipe(fdC);

pid_t pidC;

pidC=fork();

flagCount=1;

//C進程

if(pidC==0)

{

close(fdC[0]);

int runtimeC=0;

struct timeval startC,endC;

n=gettimeofday(&startC, NULL);

gettimeofday(&endC, NULL);

float distanceC=0;

//空跑180秒,每3秒向管道內寫入已運行時間

//採用網頁顯示,主進程與A之間有180個像素,故速度爲1

while((runtimeC=(endC.tv_sec-startC.tv_sec))<=180)

{

sleep(3);

char timeC[20]={0};

distanceC=1*runtimeC;

sprintf(timeC,"%.2f",distanceC);

gettimeofday(&endC, NULL);  

int n=write(fdC[1],timeC,sizeof(timeC));

printf("\n%dC寫入管道\n",n);

}

//向父進程發送信號

if(kill(getppid(),SIGINT)==-1)


{

printf("process C send fail");

exit(0);

}

exit(0);

}

}

char readA[20];

char widthA[20]={0};

char widthB[20]={0};

char readC[20];

char widthC[20]={0};

if(!flagA)

{

read(fdA[0],readA,20);

strcpy(widthA,readA);

}

else{

strcpy(widthA,"480");

strcpy(stateA,"子進程A執行完畢");

}

char readB[20];

if(!flagB)

{

read(fdB[0],readB,20);

strcpy(widthB,readB);

}

else{

strcpy(widthB,"480");

strcpy(stateB,"子進程B執行完畢");

}

char stateC[50]={0};

if(flagC==1)

{

strcpy(widthC,"0");

strcpy(stateC," ");

}

else if(flagC==2)

{

read(fdC[0],readC,20);

strcpy(widthC,readC);

strcpy(stateC,"子進程C執行中");    

}

else

{

strcpy(widthC,"180");

strcpy(stateC,"子進程C完畢");

}

listen(server_socket, 5);

int client_socket = accept(server_socket, NULL, NULL);

char buf[1024];

read(client_socket, buf, 1024);

char status[] = "HTTP/1.0 200 OK\r\n";

Char header[]="Server:DWBServer\r\nContent-Type: text/html;charset=utf-8\r\n\r\n";

char body[]="<html><head><meta http-equiv='refresh' content='3'><title>多進程併發可視化</title></head><body><div style='height:250px;width:50px;background-color: red;'>父進程</div><div style='height:8px;width:0px;background-color: #00ff2f;position: absolute;left: 60px;top: 50px;'>子進程A執行進度</div><div style='height:8px;width:0px;background-color: #00ff2f;position: absolute;left: 60px;top: 200px;'>子進程B執行進度</div><div style='height:100px;width:50px;background-color: #00ff2f;position: absolute;left: 530px;top: 0px;'>子進程A</div><div style='height:100px;width:50px;background-color: #000dff;position: absolute;left: 530px;top: 150px;'>子進程B</div><div style='height:50px;width:8px;background-color: #0b000c;position: absolute;left: 550px;top: 100px;'></div><div style='height:100px;width:50px;background-color: #f113ff;position: absolute;left: 738px;top: 80px;'>子進程C</div><div style='height:8px;width:0px;background-color: #f113ff;position: absolute;left: 558px;top: 120px;'></div></body></html>";

sprintf(body,"<html><head><meta http-equiv='refresh' content='3'><title>多進程併發可視化</title></head><body><div style='height:250px;width:50px;background-color: red;'>父進程</div><div style='height:8px;width:%spx;background-color: #00ff2f;position: absolute;left: 60px;top: 50px;'>%s</div><div style='height:8px;width:%spx;background-color: #00ff2f;position: absolute;left: 60px;top: 200px;'>%s</div><div style='height:100px;width:50px;background-color: #00ff2f;position: absolute;left: 530px;top: 0px;'>子進程A</div><div style='height:100px;width:50px;background-color: #000dff;position: absolute;left: 530px;top: 150px;'>子進程B</div><div style='height:50px;width:8px;background-color: #0b000c;position: absolute;left: 550px;top: 100px;'></div><div style='height:100px;width:50px;background-color: #f113ff;position: absolute;left: 738px;top: 80px;'>子進程C</div><div style='height:8px;width:%spx;background-color: #f113ff;position: absolute;left: 558px;top: 120px;'>%s</div></body></html>",widthA,stateA,widthB,stateB,widthC,stateC);

write(client_socket, status, sizeof(status));

write(client_socket, header, sizeof(header));

write(client_socket, body, sizeof(body));

close(client_socket);

}

}

}

close(server_socket);

return 0;

}

2018-09-06 20-44-32 的屏幕截圖.png2018-09-06 20-44-45 的屏幕截圖.png2018-09-06 20-44-52 的屏幕截圖.png2018-09-06 20-44-59 的屏幕截圖.png2018-09-06 20-45-16 的屏幕截圖.png2018-09-06 20-46-40 的屏幕截圖.png2018-09-06 20-47-08 的屏幕截圖.png2018-09-06 20-48-53 的屏幕截圖.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章