├── .gitignore ├── 2_DOS_Multiple_Assignment ├── README.md ├── T1_AB.c ├── T2_Mutex.c ├── T3_P_C.c └── T4_R_S.c ├── 3_Simple_File_System ├── README.md ├── V0.0.1 │ ├── Common.cpp │ ├── Common.h │ ├── FAT.cpp │ ├── FAT.h │ ├── FCB.cpp │ ├── FCB.h │ ├── FDT.cpp │ ├── FDT.h │ ├── OFT.cpp │ ├── OFT.h │ ├── SysStructure.cpp │ ├── SysStructure.h │ ├── main.cpp │ └── main.h ├── V0.0.2 │ ├── Common.h │ ├── SysStructure.cpp │ ├── SysStructure.h │ └── main.cpp └── reference │ └── file_sys.cpp ├── 4_Linux_Progress_Control ├── 4_2_myshell │ ├── README.md │ ├── cmd1.c │ ├── cmd2.c │ ├── cmd3.c │ ├── makefile │ └── myshell.c ├── 4_3_Pipe_Communication │ ├── README.md │ ├── makefile │ └── pipe_communication.c ├── 4_4_message_queue │ ├── README.md │ ├── makefile │ └── message_queue.c ├── 4_5_shared_memory │ ├── README.md │ ├── common.c │ ├── common.h │ ├── init.c │ ├── log.txt │ ├── makefile │ ├── receiver.c │ └── sender.c └── README.txt ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | -------------------------------------------------------------------------------- /2_DOS_Multiple_Assignment/README.md: -------------------------------------------------------------------------------- 1 | 2 | #内容要求 3 | 4 | (1) 用C语言完成线程的创建和撤消,并按先来先服务方式对多个线程进行调度。 5 | 6 | (2) 将线程调度算法修改为时间片轮转算法,实现时间片轮转调度。(也可以结合优先权,实现优先权加时间片轮转算法的线程调度。) 7 | 8 | (3) 改变时间片的大小,观察结果的变化。思考:为什么时间片不能太小或太大。 9 | 10 | (4) 假设两个线程共用同一软件资源(如某一变量,或某一数据结构),请用记录型信号量来实现对它的互斥访问。 11 | 12 | (5) 假设有两个线程共享一个可存放5个整数的缓冲,其中一个线程不停地计算1至50的平方,并将结果放入缓冲中,另一个线程不断地从缓冲中取出结果,并将它们打印出来,请用记录型信号量实现这一生产者和消费者的同步问题。 13 | 14 | (6) 实现消息缓冲通信,并与4、5中的简单通信进行比较。 15 | 16 | (7) 思考:在线程间进行消息缓冲通信时,若对消息队列的访问没有满足互斥要求,情况将会怎样? 17 | 18 | 19 | # 源文件详解 20 | ##文件列表 21 | (1) T1_AB : Print "a" "b" 22 | 23 | (2) T2_Mutex : Two thread add to Sum 24 | 25 | (3) T3_P_C : Producer & Consumer 26 | 27 | (4) T4_R_S : Sender & Receiver 28 | 29 | 30 | ##运行 31 | 32 | >github上查看gif可能会有一些卡,所以我也放到了我的简书博客上面 33 | [DOS 系列程序运行例程](http://www.jianshu.com/p/78e2542a9901) 34 | 35 | ###T1_AB 36 | 37 | ![Dos-T1-02.gif](http://upload-images.jianshu.io/upload_images/1199728-c6347ab382fa76ce.gif?imageMogr2/auto-orient/strip) 38 | 39 | ###T2_Mutex 40 | 41 | 42 | ![T2_Mutex.gif](http://upload-images.jianshu.io/upload_images/1199728-423e3369f4da30b0.gif?imageMogr2/auto-orient/strip) 43 | 44 | ###T3_P_C 45 | 46 | ![T3_Producer_Consumer.gif](http://upload-images.jianshu.io/upload_images/1199728-cdb74016a9302bb2.gif?imageMogr2/auto-orient/strip) 47 | 48 | ###T4_R_S 49 | 50 | ![T4_Sender_Receiver.gif](http://upload-images.jianshu.io/upload_images/1199728-d38132734fbddee1.gif?imageMogr2/auto-orient/strip) 51 | -------------------------------------------------------------------------------- /2_DOS_Multiple_Assignment/T1_AB.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Thread 1 : Print a 3 | * Thread 2 : Print b 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | /* ------------------------DEFINE---------------------- */ 13 | /* DOS */ 14 | #define GET_INDOS 0x34 15 | #define GET_CRIT_ERR 0x5d06 16 | 17 | /* BUFF */ 18 | #define MAX_TEXT_LEN 20 19 | #define MAX_BUF_NUM 5 20 | 21 | /* TCB */ 22 | #define MAX_TCB_NUM 5 23 | 24 | /* Thread */ 25 | #define FINISHED 0 26 | #define RUNNING 1 27 | #define READY 2 28 | #define BLOCKED 3 29 | 30 | #define STACK_SIZE 1024 31 | 32 | /* ------------------------DEFINE---------------------- */ 33 | 34 | 35 | /* -------------------------Struct-------------------------*/ 36 | /* ? */ 37 | typedef int (far *codeptr)(); 38 | 39 | typedef struct buffer buffer; 40 | typedef struct TCB TCB; 41 | typedef struct semaphore semaphore; 42 | typedef struct int_regs int_regs; 43 | 44 | 45 | struct buffer 46 | { 47 | int sender; 48 | int size; 49 | char text[MAX_TEXT_LEN]; 50 | struct buffer *next; 51 | }; 52 | 53 | /* Semaphore - Record Type*/ 54 | struct semaphore 55 | { 56 | int value; /* Semaphore value */ 57 | struct TCB *wq; /* Top Pointer of Block Queue*/ 58 | }; 59 | 60 | /* Thread Control Block */ 61 | struct TCB 62 | { 63 | unsigned char *stack; 64 | unsigned ss; 65 | unsigned sp; 66 | char state; 67 | char name[10]; 68 | struct TCB *next; 69 | struct buffer *mq; 70 | 71 | semaphore mutex; 72 | semaphore sm; 73 | }; 74 | 75 | 76 | /* private stack of thread*/ 77 | struct int_regs 78 | { 79 | unsigned BP, DI, SI, DS, ES, DX, CX, BX, AX, IP, CS, Flags, off, seg; 80 | }; 81 | 82 | 83 | /* -------------------------Struct-------------------------*/ 84 | 85 | 86 | 87 | /*-----------------------Function Define ----------------------- */ 88 | 89 | /* PRINTAB */ 90 | void T0FinishedCheck(); 91 | void T1PrintA(); 92 | void T2PrintB(); 93 | 94 | 95 | /* DOS */ 96 | void DosInit(); 97 | int DosBusy(); 98 | 99 | /* TIME */ 100 | 101 | void interrupt new_int8(); 102 | void interrupt my_swtch(); 103 | void my_delay(int n); 104 | 105 | 106 | /* TCB */ 107 | void TcbInitAll(); 108 | void TcbInit(); 109 | void TcbState(); 110 | 111 | /* THREAD */ 112 | int ThreadCreate(char *name,codeptr code,int stackLen); 113 | int ThreadCreateAt(int id,char *name,codeptr code,int stackLen); 114 | int ThreadNext(); 115 | int ThreadFinished(); 116 | void ThreadDestory(int id); 117 | void ThreadDestoryAuto(); 118 | void ThreadBlock(TCB **blkq); 119 | void ThreadWakeUp(TCB **blkq); 120 | 121 | /* BUF */ 122 | void BufInitAll(); 123 | void BufInit(buffer * bufNew); 124 | void BufPut(buffer * bufNew); 125 | void BufInsertMsgq(buffer **msgq,buffer *bufNew); 126 | buffer *BufGet(); 127 | buffer *BufRemov(buffer **msgq,int sender); 128 | 129 | /* Semaphore */ 130 | void SemInit(); 131 | void P(semaphore *sem); 132 | void V(semaphore *sem); 133 | 134 | /*------------------------Function Define ----------------------*/ 135 | 136 | 137 | /*------------------------ Variable ----------------------------*/ 138 | /* TIME */ 139 | int timeCount = 0; 140 | int timeSlice = 1; 141 | void interrupt (*old_int8)(); 142 | 143 | /* SEMAPHORE */ 144 | semaphore FreeBufMutex = {1,NULL}; 145 | semaphore FreeBufNum = {MAX_BUF_NUM,NULL}; 146 | semaphore TcbMutex = {1,NULL}; 147 | semaphore TcbEmpty = {MAX_TCB_NUM,NULL}; 148 | semaphore TcbFull = {0,NULL}; 149 | 150 | /* DOS */ 151 | char far *indosPtr = 0; 152 | char far *critErrPtr = 0; 153 | 154 | /* TCB */ 155 | TCB tcbs[MAX_TCB_NUM]; 156 | 157 | /* BUF*/ 158 | buffer * freebuf; 159 | 160 | /* Thread*/ 161 | int current; 162 | 163 | /* TCB * blkq = NULL; */ 164 | /*------------------------ Variable ----------------------------*/ 165 | 166 | 167 | 168 | int main() 169 | { 170 | /* Initialization Part */ 171 | DosInit(); 172 | TcbInitAll(); 173 | BufInit(freebuf); 174 | 175 | /* Get access to the entry address of clock intrrupt */ 176 | old_int8 = getvect(8); 177 | 178 | printf("Please Input the Time Slice \n"); 179 | scanf("%d",&timeSlice); 180 | printf("Press Any Key To Continue ......\n"); 181 | getch(); 182 | 183 | clrscr(); 184 | 185 | /*ThreadCreateAt(0,"main",(codeptr)T0FinishedCheck,STACK_SIZE);*/ 186 | 187 | tcbs[0].state = RUNNING; 188 | current = 0; 189 | 190 | ThreadCreate("T1",(codeptr)T1PrintA,STACK_SIZE); 191 | ThreadCreate("T2",(codeptr)T2PrintB,STACK_SIZE); 192 | 193 | /*TODO there is a bug ,i don't know why*/ 194 | /* ThreadCreateAt(0,"T0",(codeptr)T0FinishedCheck,STACK_SIZE); */ 195 | 196 | setvect(8, new_int8); 197 | my_swtch(); 198 | 199 | TcbState(); 200 | while(!ThreadFinished()); 201 | 202 | /* ThreadDestory(0); */ 203 | TcbState(); 204 | setvect(8, old_int8); /* Recover old clock interrupt */ 205 | ThreadDestory(0); 206 | 207 | return 0; 208 | } 209 | 210 | /** 211 | * [T0FinishedCheck #0 ] 212 | * Monitor all the thread except for thread #0. 213 | * To check if they are all end. 214 | * if so end the entire system. 215 | */ 216 | 217 | /* 218 | void T0FinishedCheck() 219 | { 220 | printf("T0 is Running\n"); 221 | while(!ThreadFinished()) 222 | { 223 | printf("_"); 224 | my_delay(5); 225 | } 226 | 227 | printf("\n End of All Threads\n"); 228 | } 229 | */ 230 | 231 | /** 232 | * [T1PrintA #1] 233 | * Repeat output character "a" 234 | * In the end ,destory itself 235 | */ 236 | void T1PrintA() 237 | { 238 | int i; 239 | for(i = 0;i < 50; i++) 240 | { 241 | putchar('a'); 242 | my_delay(4); 243 | } 244 | } 245 | 246 | /** 247 | * [T2PrintB #2] 248 | * Repeat output character "b" 249 | * In the end ,destory itself 250 | */ 251 | void T2PrintB() 252 | { 253 | int i; 254 | for(i = 0;i < 30; i++) 255 | { 256 | putchar('b'); 257 | my_delay(5); 258 | } 259 | } 260 | 261 | 262 | /*------------------------ DOS ----------------------- */ 263 | /** 264 | * [DosInit description] 265 | */ 266 | void DosInit() 267 | { 268 | union REGS regs; 269 | struct SREGS segregs; 270 | regs.h.ah = GET_INDOS; 271 | intdosx(®s, ®s, &segregs); 272 | indosPtr = MK_FP(segregs.es, regs.x.bx); 273 | 274 | if(_osmajor < 3) 275 | critErrPtr = indosPtr + 1; 276 | else if(_osmajor == 3 && _osminor == 0) 277 | critErrPtr = indosPtr - 1; 278 | else 279 | { 280 | regs.x.ax = GET_CRIT_ERR; 281 | intdosx(®s, ®s, &segregs); 282 | critErrPtr = MK_FP(segregs.ds, regs.x.si); 283 | } 284 | } 285 | 286 | /** 287 | * [DosBusy : Check if Dos is busy ] 288 | * @return [isBusy] 289 | */ 290 | int DosBusy() 291 | { 292 | if(indosPtr && critErrPtr) 293 | return (*indosPtr || *critErrPtr); 294 | else 295 | return -1; 296 | } 297 | 298 | 299 | /*------------------------ DOS ----------------------- */ 300 | 301 | 302 | /*----------------- Time ----------------------- */ 303 | 304 | /** 305 | * new_int8 : CPU scheduling caused by Time Slice 306 | * @return [description] 307 | */ 308 | void interrupt new_int8() 309 | { 310 | (*old_int8)(); 311 | timeCount++; 312 | 313 | if(timeCount < timeSlice || DosBusy()) 314 | return; 315 | 316 | my_swtch(); 317 | } 318 | 319 | /** 320 | * my_swtch : CPU scheduling caused by another reason 321 | * @return [description] 322 | */ 323 | void interrupt my_swtch() 324 | { 325 | int id; 326 | 327 | id = ThreadNext(); 328 | if(id < 0) 329 | { 330 | printf("No Thread is Running\n"); 331 | return; 332 | } 333 | 334 | disable(); 335 | 336 | tcbs[current].ss = _SS; 337 | tcbs[current].sp = _SP; 338 | if(tcbs[current].state == RUNNING) 339 | tcbs[current].state = READY; 340 | 341 | /*id = 0;*/ 342 | 343 | _SS = tcbs[id].ss; 344 | _SP = tcbs[id].sp; 345 | tcbs[id].state = RUNNING; 346 | current = id; 347 | timeCount = 0; 348 | enable(); 349 | } 350 | 351 | /** 352 | * my_delay : do nothing but delay time 353 | */ 354 | 355 | void my_delay(int n) 356 | { 357 | int i; 358 | int j; 359 | int k; 360 | for(k = 0; k < n; k ++) 361 | { 362 | for(i = 0; i < 100; i++) 363 | { 364 | for(j = 0; j < 500; j++) 365 | { 366 | /*Do Nothing*/ 367 | } 368 | } 369 | } 370 | 371 | } 372 | 373 | /*------------------------ Time ----------------------- */ 374 | 375 | 376 | /*------------------------ Tcb ----------------------- */ 377 | /** 378 | * [TcbInitAll :Init All Tcbs] 379 | */ 380 | void TcbInitAll() 381 | { 382 | int id; 383 | for(id = 0; id < MAX_TCB_NUM; id++) 384 | { 385 | TcbInit(id); 386 | } 387 | } 388 | 389 | 390 | /** 391 | * [TcbInit : Init Single Tcb] 392 | * @param id [Tcb id] 393 | */ 394 | void TcbInit(int id) 395 | { 396 | tcbs[id].stack = NULL; 397 | tcbs[id].state = FINISHED; 398 | tcbs[id].name[0] = '\0'; 399 | tcbs[id].next = NULL; 400 | tcbs[id].mq = NULL; 401 | tcbs[id].mutex.value = 1; 402 | tcbs[id].mutex.wq = NULL; 403 | tcbs[id].sm.value = 0; 404 | tcbs[id].sm.wq = NULL; 405 | } 406 | 407 | /** 408 | * [TcbState :print current tcb state] 409 | */ 410 | void TcbState() 411 | { 412 | int id; 413 | printf("\n ----- Current Thread Process -------\n"); 414 | for(id = 0; id < MAX_TCB_NUM; id++) 415 | { 416 | printf("Thread %d %9s State is ", id, tcbs[id].name); 417 | switch(tcbs[id].state) 418 | { 419 | case FINISHED: 420 | puts("FINISHED"); 421 | break; 422 | case RUNNING: 423 | puts("RUNNING"); 424 | break; 425 | case READY: 426 | puts("READY"); 427 | break; 428 | case BLOCKED: 429 | puts("BLOCKED"); 430 | break; 431 | } 432 | } 433 | 434 | } 435 | 436 | /*------------------------ Tcb ----------------------- */ 437 | 438 | /*------------------------ Thread ----------------------- */ 439 | /** 440 | * [ThreadCreate 创建新的线程] 441 | * @param name [线程的名字] 442 | * @param code [函数代码的首行地址] 443 | * @param stckLen [堆栈的大小] 444 | * @return [Tcb的ID] 445 | */ 446 | int ThreadCreate(char *name,codeptr code,int stackLen) 447 | { 448 | int id; 449 | disable(); 450 | 451 | for(id = 1; id < MAX_TCB_NUM ;id++) 452 | { 453 | if(tcbs[id].state == FINISHED) 454 | { 455 | break; 456 | } 457 | } 458 | if(id == MAX_TCB_NUM) 459 | { 460 | printf("\n Fail To Create %s \n", name); 461 | return -1; 462 | } 463 | 464 | ThreadCreateAt(id,name,code,stackLen); 465 | 466 | enable(); 467 | return id; 468 | } 469 | 470 | /** 471 | * [ThreadCreateAt description] 472 | * @param id [tcb id] 473 | * @param name [thread name] 474 | * @param code [function code address] 475 | * @param stackLen [stack length] 476 | * @return [flag -1:error] 477 | */ 478 | int ThreadCreateAt(int id,char *name,codeptr code,int stackLen) 479 | { 480 | int_regs far *regs; 481 | 482 | if(tcbs[id].state == FINISHED) 483 | { 484 | tcbs[id].stack = (unsigned char *)malloc(stackLen); 485 | regs = (struct int_regs far *)(tcbs[id].stack + stackLen); 486 | regs--; 487 | tcbs[id].ss = FP_SEG(regs); 488 | tcbs[id].sp = FP_OFF(regs); 489 | tcbs[id].state = READY; 490 | strcpy(tcbs[id].name, name); 491 | 492 | regs->DS = _DS; 493 | regs->ES = _ES; 494 | regs->IP = FP_OFF(code); 495 | regs->CS = FP_SEG(code); 496 | regs->Flags = 0x200; 497 | regs->off = FP_OFF(ThreadDestoryAuto); 498 | regs->seg = FP_SEG(ThreadDestoryAuto); 499 | 500 | printf("\n Thread %d : %s has been created \n", id, tcbs[id].name); 501 | return 1; 502 | } 503 | else 504 | { 505 | printf("Error: Creating a thread on a running thread \n"); 506 | return -1; 507 | } 508 | } 509 | 510 | /** 511 | * [ThreadDestory 线程在Tcb中的撤销] 512 | * @param id [Tcb Id] 513 | */ 514 | void ThreadDestory(int id) 515 | { 516 | 517 | disable(); 518 | 519 | free(tcbs[id].stack); 520 | TcbInit(id); 521 | printf("\n Thread %d : %s already destory\n",id,tcbs[id].name); 522 | enable(); 523 | } 524 | 525 | /** 526 | * [ThreadDestoryAuto :自动撤销当前线程] 527 | */ 528 | void ThreadDestoryAuto() 529 | { 530 | 531 | ThreadDestory(current); 532 | 533 | my_swtch(); 534 | } 535 | 536 | /** 537 | * [ThreadNext : 寻找下一个就绪线程] 538 | * @return [线程ID] 539 | */ 540 | int ThreadNext() 541 | { 542 | int id; 543 | int i; 544 | 545 | /*TcbState();*/ 546 | for(i = 1;i <= MAX_TCB_NUM;i++) 547 | { 548 | 549 | id = (current + i) % MAX_TCB_NUM; 550 | if(tcbs[id].state == READY || tcbs[id].state == RUNNING) 551 | { 552 | return id; 553 | } 554 | } 555 | 556 | return -1; 557 | } 558 | 559 | /** 560 | * [ThreadFinished 查看除了0#线程外的线程是否结束] 561 | * @return [isEnd] 562 | */ 563 | int ThreadFinished() 564 | { 565 | int id; 566 | for(id = 1; id < MAX_TCB_NUM; id++) 567 | { 568 | if(tcbs[id].state != FINISHED) 569 | { 570 | return 0; 571 | } 572 | } 573 | return 1; 574 | } 575 | 576 | /** 577 | * [ThreadBlock :Insert current thread into Block Queue] 578 | * @param blkq [Block Queue] 579 | */ 580 | void ThreadBlock(TCB **blkq) 581 | { 582 | TCB *tcbp; 583 | tcbs[current].state = BLOCKED; 584 | 585 | if((*blkq) == NULL) 586 | { 587 | (*blkq) = &tcbs[current]; 588 | } 589 | else 590 | { 591 | tcbp = (*blkq); 592 | while(tcbp->next != NULL) 593 | { 594 | tcbp = tcbp->next; 595 | } 596 | tcbp->next = &tcbs[current]; 597 | } 598 | 599 | tcbs[current].next = NULL; 600 | 601 | my_swtch(); 602 | } 603 | 604 | /** 605 | * [ThreadWakeUp : Wake Up the Thread on the top of Block Queue] 606 | * @param blkq [Block Queue] 607 | */ 608 | void ThreadWakeUp(TCB **blkq) 609 | { 610 | struct TCB *tcbp; 611 | if((*blkq) == NULL) 612 | return; 613 | tcbp = (*blkq); 614 | (*blkq) = (*blkq)->next; 615 | tcbp->state = READY; 616 | tcbp->next = NULL; 617 | } 618 | 619 | /*------------------------ Thread ----------------------- */ 620 | 621 | /*------------------------ Buffer ----------------------- */ 622 | /** 623 | * [BufInitAll :Init whole buffer queue] 624 | */ 625 | void BufInitAll() 626 | { 627 | struct buffer *bufPtr,*bufNew; 628 | int i; 629 | 630 | BufInit(freebuf); 631 | bufNew = freebuf; 632 | bufPtr = freebuf; 633 | 634 | for(i = 1; i < MAX_BUF_NUM; i++) 635 | { 636 | BufInit(bufNew); 637 | bufPtr->next = bufNew; 638 | bufPtr = bufNew; 639 | } 640 | 641 | bufPtr->next = NULL; 642 | } 643 | 644 | /** 645 | * [BufInit Init one buffer] 646 | * @param bufNew [buffer pointer] 647 | * @return [Null] 648 | */ 649 | void BufInit(buffer *bufNew) 650 | { 651 | bufNew = (buffer *)malloc(sizeof(buffer)); 652 | bufNew->sender = -1; 653 | bufNew->size = 0; 654 | bufNew->text[0] = '\0'; 655 | } 656 | 657 | /* Insert Message to Available Buffer Queue*/ 658 | /** 659 | * [BufPut : Insert Message to Available Buffer Queue] 660 | * @param bufNew [new buffer] 661 | * @return [Null] 662 | */ 663 | void BufPut(buffer *bufNew) 664 | { 665 | struct buffer *bufPtr = freebuf; 666 | if(freebuf == NULL){ 667 | freebuf = bufNew; 668 | } 669 | else 670 | { 671 | while(bufPtr->next != NULL) 672 | { 673 | bufPtr = bufPtr->next; 674 | } 675 | 676 | bufPtr->next = bufNew; 677 | } 678 | bufNew->next = NULL; 679 | } 680 | 681 | /** 682 | * [BufInsertMsgq Insert Buffer to Message Queue ] 683 | * @param msgq [message queue] 684 | * @param bufNew [buffer queue header TODO] 685 | * @return [Null] 686 | */ 687 | /* TODO */ 688 | void BufInsertMsgq(buffer **msgq,buffer *bufNew) 689 | { 690 | buffer *bufPtr; 691 | 692 | if(bufNew == NULL) 693 | { 694 | return; 695 | } 696 | /* Message */ 697 | if((*msgq) == NULL) 698 | { 699 | (*msgq) = bufNew; 700 | } 701 | else 702 | { 703 | bufPtr = (*msgq); 704 | while(bufPtr->next != NULL) 705 | { 706 | bufPtr = bufPtr->next; 707 | } 708 | 709 | bufPtr->next = bufNew; 710 | } 711 | 712 | bufNew->next = NULL; 713 | } 714 | 715 | /** 716 | * [BufGet : Get Available Buffer Area] 717 | * @return [buffer] 718 | */ 719 | buffer *BufGet() 720 | { 721 | buffer *bufNew; 722 | 723 | bufNew = freebuf; 724 | freebuf = freebuf->next; 725 | 726 | return bufNew; 727 | } 728 | 729 | /** 730 | * [BufRemov : Remove one buffer created by sender] 731 | * @param msgq [message queue] 732 | * @param sender [sender id] 733 | * @return [buffer] 734 | */ 735 | buffer *BufRemov(buffer **msgq,int sender) 736 | { 737 | buffer *bufPtr, *bufNew; 738 | bufPtr = (*msgq); 739 | 740 | /* if the head of message queue then pop it*/ 741 | if(bufPtr->sender == sender) 742 | { 743 | bufNew = bufPtr; 744 | (*msgq) = bufNew->next; 745 | bufNew->next = NULL; 746 | return bufNew; 747 | } 748 | 749 | /* Find buffer sent by sender */ 750 | while(bufPtr->next != NULL && bufPtr->next->sender != sender) 751 | bufPtr = bufPtr->next; 752 | 753 | /* Can't find ,return null */ 754 | if(bufPtr->next == NULL) 755 | return NULL; 756 | 757 | bufNew = bufPtr->next; 758 | bufPtr->next = bufNew->next; 759 | bufNew->next = NULL; 760 | return bufNew; 761 | } 762 | /*------------------------ Buffer ----------------------- */ 763 | 764 | /*------------------------ Semaphore ----------------------- */ 765 | /** 766 | * [SemInit : init the value of semaphore ] 767 | */ 768 | void SemInit() 769 | { 770 | /* 771 | FreeBufMutexf = {1,NULL}; 772 | FreeBufNum = {MAX_BUF_NUM,NULL}; 773 | 774 | TcbMutex = {1,NULL}; 775 | TcbEmpty = {MAX_TCB_NUM,NULL}; 776 | TcbFull = {0,NULL}; 777 | */ 778 | } 779 | 780 | /** 781 | * [P : P Operation] 782 | * @param sem [semaphore pointer] 783 | */ 784 | void P(semaphore *sem) 785 | { 786 | struct TCB **blkq; 787 | disable(); 788 | 789 | sem->value--; 790 | /* There is no available resources */ 791 | if(sem->value < 0) 792 | { 793 | blkq = &(sem->wq); 794 | /* Insert current thread to Block Queue */ 795 | ThreadBlock(blkq); 796 | } 797 | enable(); 798 | } 799 | 800 | /** 801 | * [V : V operation] 802 | * @param sem [semaphore pointer] 803 | */ 804 | void V(semaphore *sem) 805 | { 806 | struct TCB **blkq; 807 | disable(); 808 | sem->value++; 809 | /* There are block threads in Block Queue */ 810 | if(sem->value <= 0) 811 | { 812 | blkq = &(sem->wq); 813 | /* Wake Up the top thread from Block Queue*/ 814 | ThreadWakeUp(blkq); 815 | } 816 | enable(); 817 | } 818 | 819 | /*------------------------ Semaphore ----------------------- */ 820 | -------------------------------------------------------------------------------- /2_DOS_Multiple_Assignment/T2_Mutex.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Task2: Mutex Operation 3 | * Thread 1 : Add to Sum +1 4 | * Thread 2 : Add to Sum +2 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | /* ------------------------DEFINE---------------------- */ 14 | /* DOS */ 15 | #define GET_INDOS 0x34 16 | #define GET_CRIT_ERR 0x5d06 17 | 18 | /* BUFF */ 19 | #define MAX_TEXT_LEN 20 20 | #define MAX_BUF_NUM 5 21 | 22 | /* TCB */ 23 | #define MAX_TCB_NUM 5 24 | 25 | /* Thread */ 26 | #define FINISHED 0 27 | #define RUNNING 1 28 | #define READY 2 29 | #define BLOCKED 3 30 | 31 | #define STACK_SIZE 1024 32 | 33 | /* ------------------------DEFINE---------------------- */ 34 | 35 | 36 | /* -------------------------Struct-------------------------*/ 37 | /* ? */ 38 | typedef int (far *codeptr)(); 39 | 40 | typedef struct buffer buffer; 41 | typedef struct TCB TCB; 42 | typedef struct semaphore semaphore; 43 | typedef struct int_regs int_regs; 44 | 45 | 46 | struct buffer 47 | { 48 | int sender; 49 | int size; 50 | char text[MAX_TEXT_LEN]; 51 | struct buffer *next; 52 | }; 53 | 54 | /* Semaphore - Record Type*/ 55 | struct semaphore 56 | { 57 | int value; /* Semaphore value */ 58 | struct TCB *wq; /* Top Pointer of Block Queue*/ 59 | }; 60 | 61 | /* Thread Control Block */ 62 | struct TCB 63 | { 64 | unsigned char *stack; 65 | unsigned ss; 66 | unsigned sp; 67 | char state; 68 | char name[10]; 69 | struct TCB *next; 70 | struct buffer *mq; 71 | 72 | semaphore mutex; 73 | semaphore sm; 74 | }; 75 | 76 | 77 | /* private stack of thread*/ 78 | struct int_regs 79 | { 80 | unsigned BP, DI, SI, DS, ES, DX, CX, BX, AX, IP, CS, Flags, off, seg; 81 | }; 82 | 83 | 84 | /* -------------------------Struct-------------------------*/ 85 | 86 | 87 | 88 | /*-----------------------Function Define ----------------------- */ 89 | 90 | /* ADD */ 91 | void T1AddOne(); 92 | void T2AddTwo(); 93 | 94 | 95 | /* DOS */ 96 | void DosInit(); 97 | int DosBusy(); 98 | 99 | /* TIME */ 100 | 101 | void interrupt new_int8(); 102 | void interrupt my_swtch(); 103 | void my_delay(int n); 104 | 105 | 106 | /* TCB */ 107 | void TcbInitAll(); 108 | void TcbInit(); 109 | void TcbState(); 110 | 111 | /* THREAD */ 112 | int ThreadCreate(char *name,codeptr code,int stackLen); 113 | int ThreadCreateAt(int id,char *name,codeptr code,int stackLen); 114 | int ThreadNext(); 115 | int ThreadFinished(); 116 | void ThreadDestory(int id); 117 | void ThreadDestoryAuto(); 118 | void ThreadBlock(TCB **blkq); 119 | void ThreadWakeUp(TCB **blkq); 120 | 121 | /* BUF */ 122 | void BufInitAll(); 123 | void BufInit(buffer * bufNew); 124 | void BufPut(buffer * bufNew); 125 | void BufInsertMsgq(buffer **msgq,buffer *bufNew); 126 | buffer *BufGet(); 127 | buffer *BufRemov(buffer **msgq,int sender); 128 | 129 | /* Semaphore */ 130 | void SemInit(); 131 | void P(semaphore *sem); 132 | void V(semaphore *sem); 133 | 134 | /*------------------------Function Define ----------------------*/ 135 | 136 | 137 | /*------------------------ Variable ----------------------------*/ 138 | /* TIME */ 139 | int timeCount = 0; 140 | int timeSlice = 1; 141 | void interrupt (*old_int8)(); 142 | 143 | /* SEMAPHORE */ 144 | 145 | 146 | /* DOS */ 147 | char far *indosPtr = 0; 148 | char far *critErrPtr = 0; 149 | 150 | /* TCB */ 151 | TCB tcbs[MAX_TCB_NUM]; 152 | 153 | /* BUF*/ 154 | buffer * freebuf; 155 | 156 | /* Thread*/ 157 | int current; 158 | 159 | /* Add To Sum*/ 160 | semaphore mutex = {1,NULL}; 161 | 162 | int sum = 0; 163 | /*------------------------ Variable ----------------------------*/ 164 | 165 | 166 | 167 | int main() 168 | { 169 | /* Initialization Part */ 170 | DosInit(); 171 | TcbInitAll(); 172 | BufInit(freebuf); 173 | 174 | /* Get access to the entry address of clock intrrupt */ 175 | old_int8 = getvect(8); 176 | 177 | /* 178 | printf("Please Input the Time Slice \n"); 179 | scanf("%d",&timeSlice); 180 | 181 | printf("Press Any Key To Continue ......\n"); 182 | getch(); 183 | */ 184 | 185 | clrscr(); 186 | 187 | tcbs[0].state = RUNNING; 188 | current = 0; /* current thread */ 189 | sum = 0; 190 | 191 | ThreadCreate("T1",(codeptr)T1AddOne,STACK_SIZE); 192 | ThreadCreate("T2",(codeptr)T2AddTwo,STACK_SIZE); 193 | 194 | 195 | setvect(8, new_int8); 196 | my_swtch(); 197 | 198 | TcbState(); 199 | while(!ThreadFinished()); 200 | 201 | TcbState(); 202 | setvect(8, old_int8); /* Recover old clock interrupt */ 203 | printf("End : Sum is %d \n",sum); 204 | ThreadDestory(0); 205 | return 0; 206 | } 207 | 208 | void T1AddOne() 209 | { 210 | int i; 211 | int tmp; 212 | 213 | for(i=0; i<50; i++) 214 | { 215 | P(&mutex); 216 | tmp = sum; 217 | my_delay(1); 218 | tmp++; 219 | sum = tmp; 220 | printf("#1 : sum = %d \n", sum); 221 | V(&mutex); 222 | } 223 | } 224 | 225 | void T2AddTwo() 226 | { 227 | int i; 228 | int tmp; 229 | 230 | for(i=0; i<50; i++) 231 | { 232 | P(&mutex); 233 | tmp = sum; 234 | delay(5); 235 | tmp = tmp + 2; 236 | sum = tmp; 237 | printf("#2 : sum = %d \n", sum); 238 | V(&mutex); 239 | } 240 | } 241 | /*------------------------ DOS ----------------------- */ 242 | /** 243 | * [DosInit description] 244 | */ 245 | void DosInit() 246 | { 247 | union REGS regs; 248 | struct SREGS segregs; 249 | regs.h.ah = GET_INDOS; 250 | intdosx(®s, ®s, &segregs); 251 | indosPtr = MK_FP(segregs.es, regs.x.bx); 252 | 253 | if(_osmajor < 3) 254 | critErrPtr = indosPtr + 1; 255 | else if(_osmajor == 3 && _osminor == 0) 256 | critErrPtr = indosPtr - 1; 257 | else 258 | { 259 | regs.x.ax = GET_CRIT_ERR; 260 | intdosx(®s, ®s, &segregs); 261 | critErrPtr = MK_FP(segregs.ds, regs.x.si); 262 | } 263 | } 264 | 265 | /** 266 | * [DosBusy : Check if Dos is busy ] 267 | * @return [isBusy] 268 | */ 269 | int DosBusy() 270 | { 271 | if(indosPtr && critErrPtr) 272 | return (*indosPtr || *critErrPtr); 273 | else 274 | return -1; 275 | } 276 | 277 | 278 | /*------------------------ DOS ----------------------- */ 279 | 280 | 281 | /*----------------- Time ----------------------- */ 282 | 283 | /** 284 | * new_int8 : CPU scheduling caused by Time Slice 285 | * @return [description] 286 | */ 287 | void interrupt new_int8() 288 | { 289 | (*old_int8)(); 290 | timeCount++; 291 | 292 | if(timeCount < timeSlice || DosBusy()) 293 | return; 294 | 295 | my_swtch(); 296 | } 297 | 298 | /** 299 | * my_swtch : CPU scheduling caused by another reason 300 | * @return [description] 301 | */ 302 | void interrupt my_swtch() 303 | { 304 | int id; 305 | 306 | id = ThreadNext(); 307 | if(id < 0) 308 | { 309 | printf("No Thread is Running\n"); 310 | return; 311 | } 312 | 313 | disable(); 314 | 315 | tcbs[current].ss = _SS; 316 | tcbs[current].sp = _SP; 317 | if(tcbs[current].state == RUNNING) 318 | tcbs[current].state = READY; 319 | 320 | /*id = 0;*/ 321 | 322 | _SS = tcbs[id].ss; 323 | _SP = tcbs[id].sp; 324 | tcbs[id].state = RUNNING; 325 | current = id; 326 | timeCount = 0; 327 | enable(); 328 | } 329 | 330 | /** 331 | * my_delay : do nothing but delay time 332 | */ 333 | 334 | void my_delay(int n) 335 | { 336 | int i; 337 | int j; 338 | int k; 339 | for(k = 0; k < n; k ++) 340 | { 341 | for(i = 0; i < 100; i++) 342 | { 343 | for(j = 0; j < 500; j++) 344 | { 345 | /*Do Nothing*/ 346 | } 347 | } 348 | } 349 | 350 | } 351 | 352 | /*------------------------ Time ----------------------- */ 353 | 354 | 355 | /*------------------------ Tcb ----------------------- */ 356 | /** 357 | * [TcbInitAll :Init All Tcbs] 358 | */ 359 | void TcbInitAll() 360 | { 361 | int id; 362 | for(id = 0; id < MAX_TCB_NUM; id++) 363 | { 364 | TcbInit(id); 365 | } 366 | } 367 | 368 | 369 | /** 370 | * [TcbInit : Init Single Tcb] 371 | * @param id [Tcb id] 372 | */ 373 | void TcbInit(int id) 374 | { 375 | tcbs[id].stack = NULL; 376 | tcbs[id].state = FINISHED; 377 | tcbs[id].name[0] = '\0'; 378 | tcbs[id].next = NULL; 379 | tcbs[id].mq = NULL; 380 | tcbs[id].mutex.value = 1; 381 | tcbs[id].mutex.wq = NULL; 382 | tcbs[id].sm.value = 0; 383 | tcbs[id].sm.wq = NULL; 384 | } 385 | 386 | /** 387 | * [TcbState :print current tcb state] 388 | */ 389 | void TcbState() 390 | { 391 | int id; 392 | printf("\n ----- Current Thread Process -------\n"); 393 | for(id = 0; id < MAX_TCB_NUM; id++) 394 | { 395 | printf("Thread %d %9s State is ", id, tcbs[id].name); 396 | switch(tcbs[id].state) 397 | { 398 | case FINISHED: 399 | puts("FINISHED"); 400 | break; 401 | case RUNNING: 402 | puts("RUNNING"); 403 | break; 404 | case READY: 405 | puts("READY"); 406 | break; 407 | case BLOCKED: 408 | puts("BLOCKED"); 409 | break; 410 | } 411 | } 412 | 413 | } 414 | 415 | /*------------------------ Tcb ----------------------- */ 416 | 417 | /*------------------------ Thread ----------------------- */ 418 | /** 419 | * [ThreadCreate 创建新的线程] 420 | * @param name [线程的名字] 421 | * @param code [函数代码的首行地址] 422 | * @param stckLen [堆栈的大小] 423 | * @return [Tcb的ID] 424 | */ 425 | int ThreadCreate(char *name,codeptr code,int stackLen) 426 | { 427 | int id; 428 | disable(); 429 | 430 | for(id = 1; id < MAX_TCB_NUM ;id++) 431 | { 432 | if(tcbs[id].state == FINISHED) 433 | { 434 | break; 435 | } 436 | } 437 | if(id == MAX_TCB_NUM) 438 | { 439 | printf("\n Fail To Create %s \n", name); 440 | return -1; 441 | } 442 | 443 | ThreadCreateAt(id,name,code,stackLen); 444 | 445 | enable(); 446 | return id; 447 | } 448 | 449 | /** 450 | * [ThreadCreateAt description] 451 | * @param id [tcb id] 452 | * @param name [thread name] 453 | * @param code [function code address] 454 | * @param stackLen [stack length] 455 | * @return [flag -1:error] 456 | */ 457 | int ThreadCreateAt(int id,char *name,codeptr code,int stackLen) 458 | { 459 | int_regs far *regs; 460 | 461 | if(tcbs[id].state == FINISHED) 462 | { 463 | tcbs[id].stack = (unsigned char *)malloc(stackLen); 464 | regs = (struct int_regs far *)(tcbs[id].stack + stackLen); 465 | regs--; 466 | tcbs[id].ss = FP_SEG(regs); 467 | tcbs[id].sp = FP_OFF(regs); 468 | tcbs[id].state = READY; 469 | strcpy(tcbs[id].name, name); 470 | 471 | regs->DS = _DS; 472 | regs->ES = _ES; 473 | regs->IP = FP_OFF(code); 474 | regs->CS = FP_SEG(code); 475 | regs->Flags = 0x200; 476 | regs->off = FP_OFF(ThreadDestoryAuto); 477 | regs->seg = FP_SEG(ThreadDestoryAuto); 478 | 479 | printf("\n Thread %d : %s has been created \n", id, tcbs[id].name); 480 | return 1; 481 | } 482 | else 483 | { 484 | printf("Error: Creating a thread on a running thread \n"); 485 | return -1; 486 | } 487 | } 488 | 489 | /** 490 | * [ThreadDestory 线程在Tcb中的撤销] 491 | * @param id [Tcb Id] 492 | */ 493 | void ThreadDestory(int id) 494 | { 495 | 496 | disable(); 497 | 498 | free(tcbs[id].stack); 499 | TcbInit(id); 500 | printf("\n Thread %d : %s already destory\n",id,tcbs[id].name); 501 | enable(); 502 | } 503 | 504 | /** 505 | * [ThreadDestoryAuto :自动撤销当前线程] 506 | */ 507 | void ThreadDestoryAuto() 508 | { 509 | 510 | ThreadDestory(current); 511 | 512 | my_swtch(); 513 | } 514 | 515 | /** 516 | * [ThreadNext : 寻找下一个就绪线程] 517 | * @return [线程ID] 518 | */ 519 | int ThreadNext() 520 | { 521 | int id; 522 | int i; 523 | 524 | /* TcbState(); */ 525 | for(i = 1;i <= MAX_TCB_NUM;i++) 526 | { 527 | 528 | id = (current + i) % MAX_TCB_NUM; 529 | if(tcbs[id].state == READY || tcbs[id].state == RUNNING) 530 | { 531 | return id; 532 | } 533 | } 534 | 535 | return -1; 536 | } 537 | 538 | /** 539 | * [ThreadFinished 查看除了0#线程外的线程是否结束] 540 | * @return [isEnd] 541 | */ 542 | int ThreadFinished() 543 | { 544 | int id; 545 | for(id = 1; id < MAX_TCB_NUM; id++) 546 | { 547 | if(tcbs[id].state != FINISHED) 548 | { 549 | return 0; 550 | } 551 | } 552 | return 1; 553 | } 554 | 555 | /** 556 | * [ThreadBlock :Insert current thread into Block Queue] 557 | * @param blkq [Block Queue] 558 | */ 559 | void ThreadBlock(TCB **blkq) 560 | { 561 | TCB *tcbp; 562 | tcbs[current].state = BLOCKED; 563 | 564 | if((*blkq) == NULL) 565 | { 566 | (*blkq) = &tcbs[current]; 567 | } 568 | else 569 | { 570 | tcbp = (*blkq); 571 | while(tcbp->next != NULL) 572 | { 573 | tcbp = tcbp->next; 574 | } 575 | tcbp->next = &tcbs[current]; 576 | } 577 | 578 | tcbs[current].next = NULL; 579 | 580 | my_swtch(); 581 | } 582 | 583 | /** 584 | * [ThreadWakeUp : Wake Up the Thread on the top of Block Queue] 585 | * @param blkq [Block Queue] 586 | */ 587 | void ThreadWakeUp(TCB **blkq) 588 | { 589 | struct TCB *tcbp; 590 | if((*blkq) == NULL) 591 | return; 592 | tcbp = (*blkq); 593 | (*blkq) = (*blkq)->next; 594 | tcbp->state = READY; 595 | tcbp->next = NULL; 596 | } 597 | 598 | /*------------------------ Thread ----------------------- */ 599 | 600 | /*------------------------ Buffer ----------------------- */ 601 | /** 602 | * [BufInitAll :Init whole buffer queue] 603 | */ 604 | void BufInitAll() 605 | { 606 | struct buffer *bufPtr,*bufNew; 607 | int i; 608 | 609 | BufInit(freebuf); 610 | bufNew = freebuf; 611 | bufPtr = freebuf; 612 | 613 | for(i = 1; i < MAX_BUF_NUM; i++) 614 | { 615 | BufInit(bufNew); 616 | bufPtr->next = bufNew; 617 | bufPtr = bufNew; 618 | } 619 | 620 | bufPtr->next = NULL; 621 | } 622 | 623 | /** 624 | * [BufInit Init one buffer] 625 | * @param bufNew [buffer pointer] 626 | * @return [Null] 627 | */ 628 | void BufInit(buffer *bufNew) 629 | { 630 | bufNew = (buffer *)malloc(sizeof(buffer)); 631 | bufNew->sender = -1; 632 | bufNew->size = 0; 633 | bufNew->text[0] = '\0'; 634 | } 635 | 636 | /* Insert Message to Available Buffer Queue*/ 637 | /** 638 | * [BufPut : Insert Message to Available Buffer Queue] 639 | * @param bufNew [new buffer] 640 | * @return [Null] 641 | */ 642 | void BufPut(buffer *bufNew) 643 | { 644 | struct buffer *bufPtr = freebuf; 645 | if(freebuf == NULL){ 646 | freebuf = bufNew; 647 | } 648 | else 649 | { 650 | while(bufPtr->next != NULL) 651 | { 652 | bufPtr = bufPtr->next; 653 | } 654 | 655 | bufPtr->next = bufNew; 656 | } 657 | bufNew->next = NULL; 658 | } 659 | 660 | /** 661 | * [BufInsertMsgq Insert Buffer to Message Queue ] 662 | * @param msgq [message queue] 663 | * @param bufNew [buffer queue header TODO] 664 | * @return [Null] 665 | */ 666 | /* TODO */ 667 | void BufInsertMsgq(buffer **msgq,buffer *bufNew) 668 | { 669 | buffer *bufPtr; 670 | 671 | if(bufNew == NULL) 672 | { 673 | return; 674 | } 675 | /* Message */ 676 | if((*msgq) == NULL) 677 | { 678 | (*msgq) = bufNew; 679 | } 680 | else 681 | { 682 | bufPtr = (*msgq); 683 | while(bufPtr->next != NULL) 684 | { 685 | bufPtr = bufPtr->next; 686 | } 687 | 688 | bufPtr->next = bufNew; 689 | } 690 | 691 | bufNew->next = NULL; 692 | } 693 | 694 | /** 695 | * [BufGet : Get Available Buffer Area] 696 | * @return [buffer] 697 | */ 698 | buffer *BufGet() 699 | { 700 | buffer *bufNew; 701 | 702 | bufNew = freebuf; 703 | freebuf = freebuf->next; 704 | 705 | return bufNew; 706 | } 707 | 708 | /** 709 | * [BufRemov : Remove one buffer created by sender] 710 | * @param msgq [message queue] 711 | * @param sender [sender id] 712 | * @return [buffer] 713 | */ 714 | buffer *BufRemov(buffer **msgq,int sender) 715 | { 716 | buffer *bufPtr, *bufNew; 717 | bufPtr = (*msgq); 718 | 719 | /* if the head of message queue then pop it*/ 720 | if(bufPtr->sender == sender) 721 | { 722 | bufNew = bufPtr; 723 | (*msgq) = bufNew->next; 724 | bufNew->next = NULL; 725 | return bufNew; 726 | } 727 | 728 | /* Find buffer sent by sender */ 729 | while(bufPtr->next != NULL && bufPtr->next->sender != sender) 730 | bufPtr = bufPtr->next; 731 | 732 | /* Can't find ,return null */ 733 | if(bufPtr->next == NULL) 734 | return NULL; 735 | 736 | bufNew = bufPtr->next; 737 | bufPtr->next = bufNew->next; 738 | bufNew->next = NULL; 739 | return bufNew; 740 | } 741 | /*------------------------ Buffer ----------------------- */ 742 | 743 | /*------------------------ Semaphore ----------------------- */ 744 | /** 745 | * [SemInit : init the value of semaphore ] 746 | */ 747 | void SemInit() 748 | { 749 | /* 750 | FreeBufMutexf = {1,NULL}; 751 | FreeBufNum = {MAX_BUF_NUM,NULL}; 752 | 753 | TcbMutex = {1,NULL}; 754 | TcbEmpty = {MAX_TCB_NUM,NULL}; 755 | TcbFull = {0,NULL}; 756 | */ 757 | } 758 | 759 | /** 760 | * [P : P Operation] 761 | * @param sem [semaphore pointer] 762 | */ 763 | void P(semaphore *sem) 764 | { 765 | struct TCB **blkq; 766 | disable(); 767 | 768 | sem->value--; 769 | /* There is no available resources */ 770 | if(sem->value < 0) 771 | { 772 | blkq = &(sem->wq); 773 | /* Insert current thread to Block Queue */ 774 | ThreadBlock(blkq); 775 | } 776 | enable(); 777 | } 778 | 779 | /** 780 | * [V : V operation] 781 | * @param sem [semaphore pointer] 782 | */ 783 | void V(semaphore *sem) 784 | { 785 | struct TCB **blkq; 786 | disable(); 787 | sem->value++; 788 | /* There are block threads in Block Queue */ 789 | if(sem->value <= 0) 790 | { 791 | blkq = &(sem->wq); 792 | /* Wake Up the top thread from Block Queue*/ 793 | ThreadWakeUp(blkq); 794 | } 795 | enable(); 796 | } 797 | 798 | /*------------------------ Semaphore ----------------------- */ 799 | -------------------------------------------------------------------------------- /2_DOS_Multiple_Assignment/T3_P_C.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Thread 1 : Producer 1-50 i^2 -> numBuf 3 | * Thread 2 : Consumer read from numBuf 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | /* ------------------------DEFINE---------------------- */ 13 | /* DOS */ 14 | #define GET_INDOS 0x34 15 | #define GET_CRIT_ERR 0x5d06 16 | 17 | /* BUFF */ 18 | #define MAX_TEXT_LEN 20 19 | #define MAX_BUF_NUM 5 20 | 21 | /* TCB */ 22 | #define MAX_TCB_NUM 5 23 | 24 | /* Thread */ 25 | #define FINISHED 0 26 | #define RUNNING 1 27 | #define READY 2 28 | #define BLOCKED 3 29 | 30 | #define STACK_SIZE 1024 31 | 32 | /* Producer & Consumer */ 33 | #define NUM_BUF_LEN 5 34 | /* ------------------------DEFINE---------------------- */ 35 | 36 | 37 | /* -------------------------Struct-------------------------*/ 38 | /* ? */ 39 | typedef int (far *codeptr)(); 40 | 41 | typedef struct buffer buffer; 42 | typedef struct TCB TCB; 43 | typedef struct semaphore semaphore; 44 | typedef struct int_regs int_regs; 45 | 46 | 47 | struct buffer 48 | { 49 | int sender; 50 | int size; 51 | char text[MAX_TEXT_LEN]; 52 | struct buffer *next; 53 | }; 54 | 55 | /* Semaphore - Record Type*/ 56 | struct semaphore 57 | { 58 | int value; /* Semaphore value */ 59 | struct TCB *wq; /* Top Pointer of Block Queue*/ 60 | }; 61 | 62 | /* Thread Control Block */ 63 | struct TCB 64 | { 65 | unsigned char *stack; 66 | unsigned ss; 67 | unsigned sp; 68 | char state; 69 | char name[10]; 70 | struct TCB *next; 71 | struct buffer *mq; 72 | 73 | semaphore mutex; 74 | semaphore sm; 75 | }; 76 | 77 | 78 | /* private stack of thread*/ 79 | struct int_regs 80 | { 81 | unsigned BP, DI, SI, DS, ES, DX, CX, BX, AX, IP, CS, Flags, off, seg; 82 | }; 83 | 84 | 85 | /* -------------------------Struct-------------------------*/ 86 | 87 | 88 | 89 | /*-----------------------Function Define ----------------------- */ 90 | 91 | /* ADD */ 92 | void T1Producer(); 93 | void T2Custemer(); 94 | 95 | 96 | /* DOS */ 97 | void DosInit(); 98 | int DosBusy(); 99 | 100 | /* TIME */ 101 | 102 | void interrupt new_int8(); 103 | void interrupt my_swtch(); 104 | void my_delay(int n); 105 | 106 | 107 | /* TCB */ 108 | void TcbInitAll(); 109 | void TcbInit(); 110 | void TcbState(); 111 | 112 | /* THREAD */ 113 | int ThreadCreate(char *name,codeptr code,int stackLen); 114 | int ThreadCreateAt(int id,char *name,codeptr code,int stackLen); 115 | int ThreadNext(); 116 | int ThreadFinished(); 117 | void ThreadDestory(int id); 118 | void ThreadDestoryAuto(); 119 | void ThreadBlock(TCB **blkq); 120 | void ThreadWakeUp(TCB **blkq); 121 | 122 | /* BUF */ 123 | void BufInitAll(); 124 | void BufInit(buffer * bufNew); 125 | void BufPut(buffer * bufNew); 126 | void BufInsertMsgq(buffer **msgq,buffer *bufNew); 127 | buffer *BufGet(); 128 | buffer *BufRemov(buffer **msgq,int sender); 129 | 130 | /* Semaphore */ 131 | void SemInit(); 132 | void P(semaphore *sem); 133 | void V(semaphore *sem); 134 | 135 | /*------------------------Function Define ----------------------*/ 136 | 137 | 138 | /*------------------------ Variable ----------------------------*/ 139 | /* TIME */ 140 | int timeCount = 0; 141 | int timeSlice = 1; 142 | void interrupt (*old_int8)(); 143 | 144 | /* SEMAPHORE */ 145 | 146 | /* 147 | semaphore FreeBufMutex = {1,NULL}; 148 | semaphore FreeBufNum = {MAX_BUF_NUM,NULL}; 149 | */ 150 | 151 | 152 | 153 | 154 | /* DOS */ 155 | char far *indosPtr = 0; 156 | char far *critErrPtr = 0; 157 | 158 | /* TCB */ 159 | TCB tcbs[MAX_TCB_NUM]; 160 | 161 | /* BUF*/ 162 | buffer * freebuf; 163 | 164 | /* Thread*/ 165 | int current; 166 | 167 | /* Test 3 : Producer & Consumer */ 168 | 169 | semaphore mutex = {1,NULL}; 170 | semaphore empty = {NUM_BUF_LEN,NULL}; 171 | semaphore full = {0,NULL}; 172 | 173 | int numBuf[NUM_BUF_LEN]; 174 | 175 | int pOut; 176 | int pIn; 177 | 178 | /*------------------------ Variable ----------------------------*/ 179 | 180 | 181 | 182 | int main() 183 | { 184 | int i; 185 | /* Initialization Part */ 186 | DosInit(); 187 | TcbInitAll(); 188 | BufInit(freebuf); 189 | 190 | /* Get access to the entry address of clock intrrupt */ 191 | old_int8 = getvect(8); 192 | 193 | 194 | clrscr(); 195 | 196 | tcbs[0].state = RUNNING; 197 | current = 0; /* current thread */ 198 | 199 | /* Init NumBuf*/ 200 | for(i = 0; i < NUM_BUF_LEN; i++) 201 | { 202 | numBuf[i] = 0; 203 | } 204 | 205 | pIn = pOut = 0; /* out/in Index for numBuf */ 206 | 207 | ThreadCreate("T1",(codeptr)T1Producer,STACK_SIZE); 208 | ThreadCreate("T2",(codeptr)T2Custemer,STACK_SIZE); 209 | 210 | 211 | setvect(8, new_int8); 212 | my_swtch(); 213 | 214 | TcbState(); 215 | while(!ThreadFinished()); 216 | 217 | TcbState(); 218 | setvect(8, old_int8); /* Recover old clock interrupt */ 219 | 220 | ThreadDestory(0); 221 | return 0; 222 | } 223 | 224 | void T1Producer() 225 | { 226 | int i; 227 | int tmp; 228 | 229 | for(i=0; i<50; i++) 230 | { 231 | tmp = i * i; 232 | P(&empty); 233 | P(&mutex); 234 | numBuf[pIn] = tmp; 235 | pIn = (pIn + 1) % NUM_BUF_LEN; 236 | my_delay(1); 237 | 238 | printf("T1: Produce %d\n",tmp); 239 | V(&mutex); 240 | V(&full); 241 | } 242 | } 243 | 244 | void T2Custemer() 245 | { 246 | int i; 247 | int tmp; 248 | 249 | for(i=0; i<50; i++) 250 | { 251 | P(&full); 252 | P(&mutex); 253 | tmp = numBuf[pOut]; 254 | pOut = (pOut + 1) % NUM_BUF_LEN; 255 | 256 | delay(5); 257 | printf("#2 : Consume %d \n",tmp); 258 | 259 | V(&mutex); 260 | V(&empty); 261 | } 262 | } 263 | /*------------------------ DOS ----------------------- */ 264 | /** 265 | * [DosInit description] 266 | */ 267 | void DosInit() 268 | { 269 | union REGS regs; 270 | struct SREGS segregs; 271 | regs.h.ah = GET_INDOS; 272 | intdosx(®s, ®s, &segregs); 273 | indosPtr = MK_FP(segregs.es, regs.x.bx); 274 | 275 | if(_osmajor < 3) 276 | critErrPtr = indosPtr + 1; 277 | else if(_osmajor == 3 && _osminor == 0) 278 | critErrPtr = indosPtr - 1; 279 | else 280 | { 281 | regs.x.ax = GET_CRIT_ERR; 282 | intdosx(®s, ®s, &segregs); 283 | critErrPtr = MK_FP(segregs.ds, regs.x.si); 284 | } 285 | } 286 | 287 | /** 288 | * [DosBusy : Check if Dos is busy ] 289 | * @return [isBusy] 290 | */ 291 | int DosBusy() 292 | { 293 | if(indosPtr && critErrPtr) 294 | return (*indosPtr || *critErrPtr); 295 | else 296 | return -1; 297 | } 298 | 299 | 300 | /*------------------------ DOS ----------------------- */ 301 | 302 | 303 | /*----------------- Time ----------------------- */ 304 | 305 | /** 306 | * new_int8 : CPU scheduling caused by Time Slice 307 | * @return [description] 308 | */ 309 | void interrupt new_int8() 310 | { 311 | (*old_int8)(); 312 | timeCount++; 313 | 314 | if(timeCount < timeSlice || DosBusy()) 315 | return; 316 | 317 | my_swtch(); 318 | } 319 | 320 | /** 321 | * my_swtch : CPU scheduling caused by another reason 322 | * @return [description] 323 | */ 324 | void interrupt my_swtch() 325 | { 326 | int id; 327 | 328 | id = ThreadNext(); 329 | if(id < 0) 330 | { 331 | printf("No Thread is Running\n"); 332 | return; 333 | } 334 | 335 | disable(); 336 | 337 | tcbs[current].ss = _SS; 338 | tcbs[current].sp = _SP; 339 | if(tcbs[current].state == RUNNING) 340 | tcbs[current].state = READY; 341 | 342 | /*id = 0;*/ 343 | 344 | _SS = tcbs[id].ss; 345 | _SP = tcbs[id].sp; 346 | tcbs[id].state = RUNNING; 347 | current = id; 348 | timeCount = 0; 349 | enable(); 350 | } 351 | 352 | /** 353 | * my_delay : do nothing but delay time 354 | */ 355 | 356 | void my_delay(int n) 357 | { 358 | int i; 359 | int j; 360 | int k; 361 | for(k = 0; k < n; k ++) 362 | { 363 | for(i = 0; i < 100; i++) 364 | { 365 | for(j = 0; j < 500; j++) 366 | { 367 | /*Do Nothing*/ 368 | } 369 | } 370 | } 371 | 372 | } 373 | 374 | /*------------------------ Time ----------------------- */ 375 | 376 | 377 | /*------------------------ Tcb ----------------------- */ 378 | /** 379 | * [TcbInitAll :Init All Tcbs] 380 | */ 381 | void TcbInitAll() 382 | { 383 | int id; 384 | for(id = 0; id < MAX_TCB_NUM; id++) 385 | { 386 | TcbInit(id); 387 | } 388 | } 389 | 390 | 391 | /** 392 | * [TcbInit : Init Single Tcb] 393 | * @param id [Tcb id] 394 | */ 395 | void TcbInit(int id) 396 | { 397 | tcbs[id].stack = NULL; 398 | tcbs[id].state = FINISHED; 399 | tcbs[id].name[0] = '\0'; 400 | tcbs[id].next = NULL; 401 | tcbs[id].mq = NULL; 402 | tcbs[id].mutex.value = 1; 403 | tcbs[id].mutex.wq = NULL; 404 | tcbs[id].sm.value = 0; 405 | tcbs[id].sm.wq = NULL; 406 | } 407 | 408 | /** 409 | * [TcbState :print current tcb state] 410 | */ 411 | void TcbState() 412 | { 413 | int id; 414 | printf("\n ----- Current Thread Process -------\n"); 415 | for(id = 0; id < MAX_TCB_NUM; id++) 416 | { 417 | printf("Thread %d %9s State is ", id, tcbs[id].name); 418 | switch(tcbs[id].state) 419 | { 420 | case FINISHED: 421 | puts("FINISHED"); 422 | break; 423 | case RUNNING: 424 | puts("RUNNING"); 425 | break; 426 | case READY: 427 | puts("READY"); 428 | break; 429 | case BLOCKED: 430 | puts("BLOCKED"); 431 | break; 432 | } 433 | } 434 | 435 | } 436 | 437 | /*------------------------ Tcb ----------------------- */ 438 | 439 | /*------------------------ Thread ----------------------- */ 440 | /** 441 | * [ThreadCreate 创建新的线程] 442 | * @param name [线程的名字] 443 | * @param code [函数代码的首行地址] 444 | * @param stckLen [堆栈的大小] 445 | * @return [Tcb的ID] 446 | */ 447 | int ThreadCreate(char *name,codeptr code,int stackLen) 448 | { 449 | int id; 450 | disable(); 451 | 452 | for(id = 1; id < MAX_TCB_NUM ;id++) 453 | { 454 | if(tcbs[id].state == FINISHED) 455 | { 456 | break; 457 | } 458 | } 459 | if(id == MAX_TCB_NUM) 460 | { 461 | printf("\n Fail To Create %s \n", name); 462 | return -1; 463 | } 464 | 465 | ThreadCreateAt(id,name,code,stackLen); 466 | 467 | enable(); 468 | return id; 469 | } 470 | 471 | /** 472 | * [ThreadCreateAt description] 473 | * @param id [tcb id] 474 | * @param name [thread name] 475 | * @param code [function code address] 476 | * @param stackLen [stack length] 477 | * @return [flag -1:error] 478 | */ 479 | int ThreadCreateAt(int id,char *name,codeptr code,int stackLen) 480 | { 481 | int_regs far *regs; 482 | 483 | if(tcbs[id].state == FINISHED) 484 | { 485 | tcbs[id].stack = (unsigned char *)malloc(stackLen); 486 | regs = (struct int_regs far *)(tcbs[id].stack + stackLen); 487 | regs--; 488 | tcbs[id].ss = FP_SEG(regs); 489 | tcbs[id].sp = FP_OFF(regs); 490 | tcbs[id].state = READY; 491 | strcpy(tcbs[id].name, name); 492 | 493 | regs->DS = _DS; 494 | regs->ES = _ES; 495 | regs->IP = FP_OFF(code); 496 | regs->CS = FP_SEG(code); 497 | regs->Flags = 0x200; 498 | regs->off = FP_OFF(ThreadDestoryAuto); 499 | regs->seg = FP_SEG(ThreadDestoryAuto); 500 | 501 | printf("\n Thread %d : %s has been created \n", id, tcbs[id].name); 502 | return 1; 503 | } 504 | else 505 | { 506 | printf("Error: Creating a thread on a running thread \n"); 507 | return -1; 508 | } 509 | } 510 | 511 | /** 512 | * [ThreadDestory 线程在Tcb中的撤销] 513 | * @param id [Tcb Id] 514 | */ 515 | void ThreadDestory(int id) 516 | { 517 | 518 | disable(); 519 | 520 | free(tcbs[id].stack); 521 | TcbInit(id); 522 | printf("\n Thread %d : %s already destory\n",id,tcbs[id].name); 523 | enable(); 524 | } 525 | 526 | /** 527 | * [ThreadDestoryAuto :自动撤销当前线程] 528 | */ 529 | void ThreadDestoryAuto() 530 | { 531 | 532 | ThreadDestory(current); 533 | 534 | my_swtch(); 535 | } 536 | 537 | /** 538 | * [ThreadNext : 寻找下一个就绪线程] 539 | * @return [线程ID] 540 | */ 541 | int ThreadNext() 542 | { 543 | int id; 544 | int i; 545 | 546 | /* TcbState(); */ 547 | for(i = 1;i <= MAX_TCB_NUM;i++) 548 | { 549 | 550 | id = (current + i) % MAX_TCB_NUM; 551 | if(tcbs[id].state == READY || tcbs[id].state == RUNNING) 552 | { 553 | return id; 554 | } 555 | } 556 | 557 | return -1; 558 | } 559 | 560 | /** 561 | * [ThreadFinished 查看除了0#线程外的线程是否结束] 562 | * @return [isEnd] 563 | */ 564 | int ThreadFinished() 565 | { 566 | int id; 567 | for(id = 1; id < MAX_TCB_NUM; id++) 568 | { 569 | if(tcbs[id].state != FINISHED) 570 | { 571 | return 0; 572 | } 573 | } 574 | return 1; 575 | } 576 | 577 | /** 578 | * [ThreadBlock :Insert current thread into Block Queue] 579 | * @param blkq [Block Queue] 580 | */ 581 | void ThreadBlock(TCB **blkq) 582 | { 583 | TCB *tcbp; 584 | tcbs[current].state = BLOCKED; 585 | 586 | if((*blkq) == NULL) 587 | { 588 | (*blkq) = &tcbs[current]; 589 | } 590 | else 591 | { 592 | tcbp = (*blkq); 593 | while(tcbp->next != NULL) 594 | { 595 | tcbp = tcbp->next; 596 | } 597 | tcbp->next = &tcbs[current]; 598 | } 599 | 600 | tcbs[current].next = NULL; 601 | 602 | my_swtch(); 603 | } 604 | 605 | /** 606 | * [ThreadWakeUp : Wake Up the Thread on the top of Block Queue] 607 | * @param blkq [Block Queue] 608 | */ 609 | void ThreadWakeUp(TCB **blkq) 610 | { 611 | struct TCB *tcbp; 612 | if((*blkq) == NULL) 613 | return; 614 | tcbp = (*blkq); 615 | (*blkq) = (*blkq)->next; 616 | tcbp->state = READY; 617 | tcbp->next = NULL; 618 | } 619 | 620 | /*------------------------ Thread ----------------------- */ 621 | 622 | /*------------------------ Buffer ----------------------- */ 623 | /** 624 | * [BufInitAll :Init whole buffer queue] 625 | */ 626 | void BufInitAll() 627 | { 628 | struct buffer *bufPtr,*bufNew; 629 | int i; 630 | 631 | BufInit(freebuf); 632 | bufNew = freebuf; 633 | bufPtr = freebuf; 634 | 635 | for(i = 1; i < MAX_BUF_NUM; i++) 636 | { 637 | BufInit(bufNew); 638 | bufPtr->next = bufNew; 639 | bufPtr = bufNew; 640 | } 641 | 642 | bufPtr->next = NULL; 643 | } 644 | 645 | /** 646 | * [BufInit Init one buffer] 647 | * @param bufNew [buffer pointer] 648 | * @return [Null] 649 | */ 650 | void BufInit(buffer *bufNew) 651 | { 652 | bufNew = (buffer *)malloc(sizeof(buffer)); 653 | bufNew->sender = -1; 654 | bufNew->size = 0; 655 | bufNew->text[0] = '\0'; 656 | } 657 | 658 | /* Insert Message to Available Buffer Queue*/ 659 | /** 660 | * [BufPut : Insert Message to Available Buffer Queue] 661 | * @param bufNew [new buffer] 662 | * @return [Null] 663 | */ 664 | void BufPut(buffer *bufNew) 665 | { 666 | struct buffer *bufPtr = freebuf; 667 | if(freebuf == NULL){ 668 | freebuf = bufNew; 669 | } 670 | else 671 | { 672 | while(bufPtr->next != NULL) 673 | { 674 | bufPtr = bufPtr->next; 675 | } 676 | 677 | bufPtr->next = bufNew; 678 | } 679 | bufNew->next = NULL; 680 | } 681 | 682 | /** 683 | * [BufInsertMsgq Insert Buffer to Message Queue ] 684 | * @param msgq [message queue] 685 | * @param bufNew [buffer queue header TODO] 686 | * @return [Null] 687 | */ 688 | /* TODO */ 689 | void BufInsertMsgq(buffer **msgq,buffer *bufNew) 690 | { 691 | buffer *bufPtr; 692 | 693 | if(bufNew == NULL) 694 | { 695 | return; 696 | } 697 | /* Message */ 698 | if((*msgq) == NULL) 699 | { 700 | (*msgq) = bufNew; 701 | } 702 | else 703 | { 704 | bufPtr = (*msgq); 705 | while(bufPtr->next != NULL) 706 | { 707 | bufPtr = bufPtr->next; 708 | } 709 | 710 | bufPtr->next = bufNew; 711 | } 712 | 713 | bufNew->next = NULL; 714 | } 715 | 716 | /** 717 | * [BufGet : Get Available Buffer Area] 718 | * @return [buffer] 719 | */ 720 | buffer *BufGet() 721 | { 722 | buffer *bufNew; 723 | 724 | bufNew = freebuf; 725 | freebuf = freebuf->next; 726 | 727 | return bufNew; 728 | } 729 | 730 | /** 731 | * [BufRemov : Remove one buffer created by sender] 732 | * @param msgq [message queue] 733 | * @param sender [sender id] 734 | * @return [buffer] 735 | */ 736 | buffer *BufRemov(buffer **msgq,int sender) 737 | { 738 | buffer *bufPtr, *bufNew; 739 | bufPtr = (*msgq); 740 | 741 | /* if the head of message queue then pop it*/ 742 | if(bufPtr->sender == sender) 743 | { 744 | bufNew = bufPtr; 745 | (*msgq) = bufNew->next; 746 | bufNew->next = NULL; 747 | return bufNew; 748 | } 749 | 750 | /* Find buffer sent by sender */ 751 | while(bufPtr->next != NULL && bufPtr->next->sender != sender) 752 | bufPtr = bufPtr->next; 753 | 754 | /* Can't find ,return null */ 755 | if(bufPtr->next == NULL) 756 | return NULL; 757 | 758 | bufNew = bufPtr->next; 759 | bufPtr->next = bufNew->next; 760 | bufNew->next = NULL; 761 | return bufNew; 762 | } 763 | /*------------------------ Buffer ----------------------- */ 764 | 765 | /*------------------------ Semaphore ----------------------- */ 766 | /** 767 | * [SemInit : init the value of semaphore ] 768 | */ 769 | void SemInit() 770 | { 771 | /* 772 | FreeBufMutexf = {1,NULL}; 773 | FreeBufNum = {MAX_BUF_NUM,NULL}; 774 | 775 | TcbMutex = {1,NULL}; 776 | TcbEmpty = {MAX_TCB_NUM,NULL}; 777 | TcbFull = {0,NULL}; 778 | */ 779 | } 780 | 781 | /** 782 | * [P : P Operation] 783 | * @param sem [semaphore pointer] 784 | */ 785 | void P(semaphore *sem) 786 | { 787 | struct TCB **blkq; 788 | disable(); 789 | 790 | sem->value--; 791 | /* There is no available resources */ 792 | if(sem->value < 0) 793 | { 794 | blkq = &(sem->wq); 795 | /* Insert current thread to Block Queue */ 796 | ThreadBlock(blkq); 797 | } 798 | enable(); 799 | } 800 | 801 | /** 802 | * [V : V operation] 803 | * @param sem [semaphore pointer] 804 | */ 805 | void V(semaphore *sem) 806 | { 807 | struct TCB **blkq; 808 | disable(); 809 | sem->value++; 810 | /* There are block threads in Block Queue */ 811 | if(sem->value <= 0) 812 | { 813 | blkq = &(sem->wq); 814 | /* Wake Up the top thread from Block Queue*/ 815 | ThreadWakeUp(blkq); 816 | } 817 | enable(); 818 | } 819 | 820 | /*------------------------ Semaphore ----------------------- */ 821 | -------------------------------------------------------------------------------- /2_DOS_Multiple_Assignment/T4_R_S.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Task 4: Use Buffer to Communication 3 | * Thread 1 : Sender 4 | * Thread 2 : Receiver 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | /* ------------------------DEFINE---------------------- */ 14 | /* DOS */ 15 | #define GET_INDOS 0x34 16 | #define GET_CRIT_ERR 0x5d06 17 | 18 | /* BUFF */ 19 | #define MAX_TEXT_LEN 20 20 | #define MAX_BUF_NUM 5 21 | 22 | /* TCB */ 23 | #define MAX_TCB_NUM 5 24 | #define TCB_NOT_FOUND -1 25 | /* Thread */ 26 | #define FINISHED 0 27 | #define RUNNING 1 28 | #define READY 2 29 | #define BLOCKED 3 30 | 31 | #define STACK_SIZE 1024 32 | 33 | /* Sender & Receiver */ 34 | #define MSG_NUM 10 35 | #define MSG_LEN 10 36 | 37 | 38 | /* ------------------------DEFINE---------------------- */ 39 | 40 | 41 | /* -------------------------Struct-------------------------*/ 42 | /* ? */ 43 | typedef int (far *codeptr)(); 44 | 45 | typedef struct buffer buffer; 46 | typedef struct TCB TCB; 47 | typedef struct semaphore semaphore; 48 | typedef struct int_regs int_regs; 49 | 50 | 51 | struct buffer 52 | { 53 | int sender; 54 | int size; 55 | char text[MAX_TEXT_LEN]; 56 | struct buffer *next; 57 | }; 58 | 59 | /* Semaphore - Record Type*/ 60 | struct semaphore 61 | { 62 | int value; /* Semaphore value */ 63 | struct TCB *wq; /* Top Pointer of Block Queue*/ 64 | }; 65 | 66 | /* Thread Control Block */ 67 | struct TCB 68 | { 69 | unsigned char *stack; 70 | unsigned ss; 71 | unsigned sp; 72 | char state; 73 | char name[10]; 74 | struct TCB *next; 75 | struct buffer *mq; 76 | 77 | semaphore mutex; 78 | semaphore sm; 79 | }; 80 | 81 | 82 | /* private stack of thread*/ 83 | struct int_regs 84 | { 85 | unsigned BP, DI, SI, DS, ES, DX, CX, BX, AX, IP, CS, Flags, off, seg; 86 | }; 87 | 88 | 89 | /* -------------------------Struct-------------------------*/ 90 | 91 | 92 | 93 | /*-----------------------Function Define ----------------------- */ 94 | 95 | /* Sender & Receiver */ 96 | void Sender(); 97 | void Receiver(); 98 | 99 | void SendPrim(char *receiver,char *msgPut,int size); 100 | int ReceivePrim(char *sender,char *msgGet); 101 | 102 | 103 | /* DOS */ 104 | void DosInit(); 105 | int DosBusy(); 106 | 107 | /* TIME */ 108 | 109 | void interrupt new_int8(); 110 | void interrupt my_swtch(); 111 | void my_delay(int n); 112 | 113 | 114 | /* TCB */ 115 | void TcbInitAll(); 116 | void TcbInit(); 117 | void TcbState(); 118 | int FindTcbByName(char *tcbName); 119 | 120 | /* THREAD */ 121 | int ThreadCreate(char *name,codeptr code,int stackLen); 122 | int ThreadCreateAt(int id,char *name,codeptr code,int stackLen); 123 | int ThreadNext(); 124 | int ThreadFinished(); 125 | void ThreadDestory(int id); 126 | void ThreadDestoryAuto(); 127 | void ThreadBlock(TCB **blkq); 128 | void ThreadWakeUp(TCB **blkq); 129 | 130 | /* BUF */ 131 | void BufInitAll(); 132 | void BufInit(buffer * bufNew); 133 | void BufPut(buffer * bufNew); 134 | void BufInsertMsgq(buffer **msgq,buffer *bufNew); 135 | buffer *BufGet(); 136 | buffer *BufRemov(buffer **msgq,int sender); 137 | 138 | /* Semaphore */ 139 | void SemInit(); 140 | void P(semaphore *sem); 141 | void V(semaphore *sem); 142 | 143 | /*------------------------Function Define ----------------------*/ 144 | 145 | 146 | /*------------------------ Variable ----------------------------*/ 147 | /* TIME */ 148 | int timeCount = 0; 149 | int timeSlice = 1; 150 | void interrupt (*old_int8)(); 151 | 152 | /* SEMAPHORE */ 153 | 154 | /* DOS */ 155 | char far *indosPtr = 0; 156 | char far *critErrPtr = 0; 157 | 158 | /* TCB */ 159 | TCB tcbs[MAX_TCB_NUM]; 160 | 161 | /* BUF*/ 162 | buffer * freebuf; 163 | 164 | /* Thread*/ 165 | int current; 166 | 167 | /* Test 3 : Producer & Consumer */ 168 | 169 | semaphore mutexFB = {1,NULL}; /* Free Buffer Mutex */ 170 | semaphore semFB = {MAX_BUF_NUM,NULL}; /* Free Buffer Semaphore */ 171 | 172 | char recvThdName[10] = "recvthd"; /*Receiver thread name*/ 173 | char sndThdName[10] = "sndthd"; /*Sender thread name*/ 174 | 175 | /*------------------------ Variable ----------------------------*/ 176 | 177 | 178 | int main() 179 | { 180 | int i; 181 | /* Initialization Part */ 182 | DosInit(); 183 | TcbInitAll(); 184 | /*TODO*/ 185 | BufInitAll(); 186 | 187 | /* Get access to the entry address of clock intrrupt */ 188 | old_int8 = getvect(8); 189 | 190 | 191 | clrscr(); 192 | 193 | tcbs[0].state = RUNNING; 194 | current = 0; /* current thread */ 195 | 196 | 197 | ThreadCreate(sndThdName,(codeptr)Sender,STACK_SIZE); 198 | ThreadCreate(recvThdName,(codeptr)Receiver,STACK_SIZE); 199 | 200 | 201 | setvect(8, new_int8); 202 | my_swtch(); 203 | 204 | TcbState(); 205 | while(!ThreadFinished()); 206 | 207 | TcbState(); 208 | setvect(8, old_int8); /* Recover old clock interrupt */ 209 | 210 | ThreadDestory(0); 211 | return 0; 212 | } 213 | 214 | 215 | void Sender() 216 | { 217 | int i; 218 | 219 | char msgPut[MSG_LEN] = "Message";/* message will be sent*/ 220 | char msgGet[MSG_LEN]; /* response message from receiver*/ 221 | /* Init msgGet*/ 222 | 223 | /* Send message 1-10 to receiver */ 224 | for(i = 0; i < MSG_NUM; i++) 225 | { 226 | /* package the new message */ 227 | msgPut[7] = i + '0'; 228 | msgPut[8] = '\0'; 229 | 230 | my_delay(10); 231 | 232 | /* send message to receiver */ 233 | SendPrim(recvThdName,msgPut,strlen(msgPut)); 234 | printf("\n Sender : %s has been sent \n",msgPut); 235 | } 236 | 237 | /* Waiting for response from receiver*/ 238 | ReceivePrim(recvThdName,msgGet); 239 | msgGet[2] = '\0'; 240 | printf("\n Sender: Receive Message from Receiver --> %s \n",msgGet); 241 | 242 | } 243 | 244 | void Receiver() 245 | { 246 | int i; 247 | int size; 248 | 249 | char msgGet[MSG_LEN]; 250 | char msgPut[MSG_LEN]; 251 | 252 | /*get message from receiver*/ 253 | for(i = 0; i < MSG_NUM-1; i++) /* TODO BUG why there is MSG_NUM -1 ??*/ 254 | { 255 | while(!(size=ReceivePrim(sndThdName,msgGet))) 256 | { 257 | printf("\n-\n"); 258 | my_delay(2); 259 | } 260 | 261 | msgGet[size] = '\0'; 262 | printf("\n Receiver : %s has been received \n",msgGet); 263 | } 264 | 265 | strcpy(msgPut,"OK"); 266 | SendPrim(sndThdName,msgPut,strlen(msgPut)); 267 | 268 | } 269 | 270 | /** 271 | * [SendPrim : Send Primitive] 272 | * @param receiver [receiver name] 273 | * @param msgPut [message will be put in] 274 | * @param size [message size] 275 | */ 276 | void SendPrim(char *receiver,char *msgPut,int size) 277 | { 278 | buffer *buff; 279 | int tcbId; 280 | 281 | /* Close Interrupt */ 282 | disable(); 283 | 284 | /* get receiver's id */ 285 | tcbId = FindTcbByName(receiver); 286 | if(tcbId == TCB_NOT_FOUND) 287 | { 288 | enable(); /* Open Interrupt */ 289 | return; 290 | } 291 | 292 | /* Get Buffer from freeBuf */ 293 | P(&semFB); 294 | P(&mutexFB); 295 | buff = BufGet(); 296 | V(&mutexFB); 297 | 298 | /* package message into buffer block*/ 299 | buff->sender = current; 300 | buff->size = size; 301 | strncpy(buff->text,msgPut,size); 302 | 303 | /* Send Buffer to Receiver's Message Queue : Tcb->mq*/ 304 | P(&(tcbs[tcbId].mutex)); 305 | BufInsertMsgq(&(tcbs[tcbId].mq),buff); 306 | V(&(tcbs[tcbId].mutex)); 307 | V(&(tcbs[tcbId].sm)); 308 | 309 | /* Open Interrupt */ 310 | enable(); 311 | } 312 | 313 | /** 314 | * [ReceivePrim : Receive Primitive] 315 | * @param sender [sender name] 316 | * @param msgGet [string pointer to store the message get from buffer] 317 | */ 318 | int ReceivePrim(char *sender,char *msgGet) 319 | { 320 | struct buffer *buff; 321 | int tcbId; 322 | int size; 323 | /* Close Interrupt */ 324 | disable(); 325 | 326 | /* Get Sender id*/ 327 | tcbId = FindTcbByName(sender); 328 | if(tcbId == TCB_NOT_FOUND) 329 | { 330 | enable(); 331 | return 0; 332 | } 333 | 334 | /* Read info from message queue to buff*/ 335 | P(&(tcbs[current].sm)); 336 | P(&(tcbs[current].mutex)); 337 | buff = BufRemov(&(tcbs[current].mq),tcbId); 338 | V(&(tcbs[current].mutex)); 339 | 340 | /* If Buffer is Null */ 341 | if(buff == NULL) 342 | { 343 | /*No message sent by sender*/ 344 | V(&tcbs[current].sm); 345 | enable(); 346 | return 0; 347 | } 348 | 349 | /* Read the message from buffer */ 350 | size = buff->size; 351 | strncpy(msgGet,buff->text,strlen(buff->text)); 352 | 353 | /* Recycle: Insert Message Into Free Buffer*/ 354 | BufInit(buff); 355 | P(&mutexFB); 356 | BufPut(buff); 357 | V(&mutexFB); 358 | V(&semFB); 359 | 360 | /* Open Interrupt */ 361 | enable(); 362 | 363 | return size; 364 | } 365 | 366 | /*------------------------ DOS ----------------------- */ 367 | /** 368 | * [DosInit description] 369 | */ 370 | void DosInit() 371 | { 372 | union REGS regs; 373 | struct SREGS segregs; 374 | regs.h.ah = GET_INDOS; 375 | intdosx(®s, ®s, &segregs); 376 | indosPtr = MK_FP(segregs.es, regs.x.bx); 377 | 378 | if(_osmajor < 3) 379 | critErrPtr = indosPtr + 1; 380 | else if(_osmajor == 3 && _osminor == 0) 381 | critErrPtr = indosPtr - 1; 382 | else 383 | { 384 | regs.x.ax = GET_CRIT_ERR; 385 | intdosx(®s, ®s, &segregs); 386 | critErrPtr = MK_FP(segregs.ds, regs.x.si); 387 | } 388 | } 389 | 390 | /** 391 | * [DosBusy : Check if Dos is busy ] 392 | * @return [isBusy] 393 | */ 394 | int DosBusy() 395 | { 396 | if(indosPtr && critErrPtr) 397 | return (*indosPtr || *critErrPtr); 398 | else 399 | return -1; 400 | } 401 | 402 | 403 | /*------------------------ DOS ----------------------- */ 404 | 405 | 406 | /*----------------- Time ----------------------- */ 407 | 408 | /** 409 | * new_int8 : CPU scheduling caused by Time Slice 410 | * @return [description] 411 | */ 412 | void interrupt new_int8() 413 | { 414 | (*old_int8)(); 415 | timeCount++; 416 | 417 | if(timeCount < timeSlice || DosBusy()) 418 | return; 419 | 420 | my_swtch(); 421 | } 422 | 423 | /** 424 | * my_swtch : CPU scheduling caused by another reason 425 | * @return [description] 426 | */ 427 | void interrupt my_swtch() 428 | { 429 | int id; 430 | 431 | id = ThreadNext(); 432 | if(id < 0) 433 | { 434 | printf("No Thread is Running\n"); 435 | return; 436 | } 437 | 438 | disable(); 439 | 440 | tcbs[current].ss = _SS; 441 | tcbs[current].sp = _SP; 442 | if(tcbs[current].state == RUNNING) 443 | tcbs[current].state = READY; 444 | 445 | /*id = 0;*/ 446 | 447 | _SS = tcbs[id].ss; 448 | _SP = tcbs[id].sp; 449 | tcbs[id].state = RUNNING; 450 | current = id; 451 | timeCount = 0; 452 | enable(); 453 | } 454 | 455 | /** 456 | * my_delay : do nothing but delay time 457 | */ 458 | 459 | void my_delay(int n) 460 | { 461 | int i; 462 | int j; 463 | int k; 464 | for(k = 0; k < n; k ++) 465 | { 466 | for(i = 0; i < 100; i++) 467 | { 468 | for(j = 0; j < 500; j++) 469 | { 470 | /*Do Nothing*/ 471 | } 472 | } 473 | } 474 | 475 | } 476 | 477 | /*------------------------ Time ----------------------- */ 478 | 479 | 480 | /*------------------------ Tcb ----------------------- */ 481 | /** 482 | * [TcbInitAll :Init All Tcbs] 483 | */ 484 | void TcbInitAll() 485 | { 486 | int id; 487 | for(id = 0; id < MAX_TCB_NUM; id++) 488 | { 489 | TcbInit(id); 490 | } 491 | } 492 | 493 | 494 | /** 495 | * [TcbInit : Init Single Tcb] 496 | * @param id [Tcb id] 497 | */ 498 | void TcbInit(int id) 499 | { 500 | tcbs[id].stack = NULL; 501 | tcbs[id].state = FINISHED; 502 | tcbs[id].name[0] = '\0'; 503 | tcbs[id].next = NULL; 504 | tcbs[id].mq = NULL; 505 | tcbs[id].mutex.value = 1; 506 | tcbs[id].mutex.wq = NULL; 507 | tcbs[id].sm.value = 0; 508 | tcbs[id].sm.wq = NULL; 509 | } 510 | 511 | /** 512 | * [TcbState :print current tcb state] 513 | */ 514 | void TcbState() 515 | { 516 | int id; 517 | printf("\n ----- Current Thread Process -------\n"); 518 | for(id = 0; id < MAX_TCB_NUM; id++) 519 | { 520 | printf("Thread %d %9s State is ", id, tcbs[id].name); 521 | switch(tcbs[id].state) 522 | { 523 | case FINISHED: 524 | puts("FINISHED"); 525 | break; 526 | case RUNNING: 527 | puts("RUNNING"); 528 | break; 529 | case READY: 530 | puts("READY"); 531 | break; 532 | case BLOCKED: 533 | puts("BLOCKED"); 534 | break; 535 | } 536 | } 537 | 538 | } 539 | 540 | int FindTcbByName(char *tcbName) 541 | { 542 | int id; 543 | 544 | for(id = 0; id < MAX_TCB_NUM; id++) 545 | { 546 | if(strcmp(tcbName,tcbs[id].name) == 0) 547 | { 548 | return id; 549 | } 550 | } 551 | 552 | /* Not Find */ 553 | printf("There is no such Thread named %s \n", tcbName); 554 | return TCB_NOT_FOUND; 555 | } 556 | /*------------------------ Tcb ----------------------- */ 557 | 558 | /*------------------------ Thread ----------------------- */ 559 | /** 560 | * [ThreadCreate : Create a new thread ] 561 | * @param name [Thread name] 562 | * @param code [first line of function code ] 563 | * @param stckLen [stack length] 564 | * @return [Tcb的ID] 565 | */ 566 | int ThreadCreate(char *name,codeptr code,int stackLen) 567 | { 568 | int id; 569 | disable(); 570 | 571 | for(id = 1; id < MAX_TCB_NUM ;id++) 572 | { 573 | if(tcbs[id].state == FINISHED) 574 | { 575 | break; 576 | } 577 | } 578 | if(id == MAX_TCB_NUM) 579 | { 580 | printf("\n Fail To Create %s \n", name); 581 | return -1; 582 | } 583 | 584 | ThreadCreateAt(id,name,code,stackLen); 585 | 586 | enable(); 587 | return id; 588 | } 589 | 590 | /** 591 | * [ThreadCreateAt description] 592 | * @param id [tcb id] 593 | * @param name [thread name] 594 | * @param code [function code address] 595 | * @param stackLen [stack length] 596 | * @return [flag -1:error] 597 | */ 598 | int ThreadCreateAt(int id,char *name,codeptr code,int stackLen) 599 | { 600 | int_regs far *regs; 601 | 602 | if(tcbs[id].state == FINISHED) 603 | { 604 | tcbs[id].stack = (unsigned char *)malloc(stackLen); 605 | regs = (struct int_regs far *)(tcbs[id].stack + stackLen); 606 | regs--; 607 | tcbs[id].ss = FP_SEG(regs); 608 | tcbs[id].sp = FP_OFF(regs); 609 | tcbs[id].state = READY; 610 | strcpy(tcbs[id].name, name); 611 | 612 | regs->DS = _DS; 613 | regs->ES = _ES; 614 | regs->IP = FP_OFF(code); 615 | regs->CS = FP_SEG(code); 616 | regs->Flags = 0x200; 617 | regs->off = FP_OFF(ThreadDestoryAuto); 618 | regs->seg = FP_SEG(ThreadDestoryAuto); 619 | 620 | printf("\n Thread %d : %s has been created \n", id, tcbs[id].name); 621 | return 1; 622 | } 623 | else 624 | { 625 | printf("Error: Creating a thread on a running thread \n"); 626 | return -1; 627 | } 628 | } 629 | 630 | /** 631 | * [ThreadDestory 线程在Tcb中的撤销] 632 | * @param id [Tcb Id] 633 | */ 634 | void ThreadDestory(int id) 635 | { 636 | 637 | disable(); 638 | 639 | free(tcbs[id].stack); 640 | TcbInit(id); 641 | printf("\n\n >>Thread%d: %s already destory\n",id,tcbs[id].name); 642 | enable(); 643 | } 644 | 645 | /** 646 | * [ThreadDestoryAuto :自动撤销当前线程] 647 | */ 648 | void ThreadDestoryAuto() 649 | { 650 | 651 | ThreadDestory(current); 652 | 653 | my_swtch(); 654 | } 655 | 656 | /** 657 | * [ThreadNext : 寻找下一个就绪线程] 658 | * @return [线程ID] 659 | */ 660 | int ThreadNext() 661 | { 662 | int id; 663 | int i; 664 | 665 | /*TcbState();*/ 666 | 667 | for(i = 1;i <= MAX_TCB_NUM;i++) 668 | { 669 | id = (current + i) % MAX_TCB_NUM; 670 | if(tcbs[id].state == READY || tcbs[id].state == RUNNING) 671 | { 672 | return id; 673 | } 674 | } 675 | 676 | return -1; 677 | } 678 | 679 | /** 680 | * [ThreadFinished 查看除了0#线程外的线程是否结束] 681 | * @return [isEnd] 682 | */ 683 | int ThreadFinished() 684 | { 685 | int id; 686 | for(id = 1; id < MAX_TCB_NUM; id++) 687 | { 688 | if(tcbs[id].state != FINISHED) 689 | { 690 | return 0; 691 | } 692 | } 693 | return 1; 694 | } 695 | 696 | /** 697 | * [ThreadBlock :Insert current thread into Block Queue] 698 | * @param blkq [Block Queue] 699 | */ 700 | void ThreadBlock(TCB **blkq) 701 | { 702 | TCB *tcbp; 703 | tcbs[current].state = BLOCKED; 704 | 705 | if((*blkq) == NULL) 706 | { 707 | (*blkq) = &tcbs[current]; 708 | } 709 | else 710 | { 711 | tcbp = (*blkq); 712 | while(tcbp->next != NULL) 713 | { 714 | tcbp = tcbp->next; 715 | } 716 | tcbp->next = &tcbs[current]; 717 | } 718 | 719 | tcbs[current].next = NULL; 720 | 721 | my_swtch(); 722 | } 723 | 724 | /** 725 | * [ThreadWakeUp : Wake Up the Thread on the top of Block Queue] 726 | * @param blkq [Block Queue] 727 | */ 728 | void ThreadWakeUp(TCB **blkq) 729 | { 730 | struct TCB *tcbp; 731 | if((*blkq) == NULL) 732 | return; 733 | tcbp = (*blkq); 734 | (*blkq) = (*blkq)->next; 735 | tcbp->state = READY; 736 | tcbp->next = NULL; 737 | } 738 | 739 | /*------------------------ Thread ----------------------- */ 740 | 741 | /*------------------------ Buffer ----------------------- */ 742 | /** 743 | * [BufInitAll :Init whole buffer queue] 744 | */ 745 | void BufInitAll() 746 | { 747 | struct buffer *bufPtr,*bufNew; 748 | int i; 749 | 750 | BufInit(freebuf); 751 | bufNew = freebuf; 752 | bufPtr = freebuf; 753 | 754 | for(i = 1; i < MAX_BUF_NUM; i++) 755 | { 756 | bufNew = (buffer *)malloc(sizeof(buffer)); 757 | BufInit(bufNew); 758 | bufPtr->next = bufNew; 759 | bufPtr = bufNew; 760 | } 761 | 762 | bufPtr->next = NULL; 763 | } 764 | 765 | /** 766 | * [BufInit Init one buffer] 767 | * @param bufNew [buffer pointer] 768 | * @return [Null] 769 | */ 770 | void BufInit(buffer *buff) 771 | { 772 | buff->sender = -1; 773 | buff->size = 0; 774 | memset(buff->text,'\0',sizeof(char)*MAX_TEXT_LEN); 775 | /* buff->text[0] = '\0'; */ 776 | } 777 | 778 | /* Insert Message to Available Buffer Queue*/ 779 | /** 780 | * [BufPut : Insert Message to Available Buffer Queue] 781 | * @param bufNew [new buffer] 782 | * @return [Null] 783 | */ 784 | void BufPut(buffer *bufNew) 785 | { 786 | struct buffer *bufPtr = freebuf; 787 | if(freebuf == NULL){ 788 | freebuf = bufNew; 789 | } 790 | else 791 | { 792 | while(bufPtr->next != NULL) 793 | { 794 | bufPtr = bufPtr->next; 795 | } 796 | 797 | bufPtr->next = bufNew; 798 | } 799 | bufNew->next = NULL; 800 | } 801 | 802 | /** 803 | * [BufInsertMsgq Insert Buffer to Message Queue ] 804 | * @param msgq [message queue] 805 | * @param bufNew [buffer queue header TODO] 806 | * @return [Null] 807 | */ 808 | /* TODO */ 809 | void BufInsertMsgq(buffer **msgq,buffer *bufNew) 810 | { 811 | buffer *bufPtr; 812 | 813 | if(bufNew == NULL) 814 | { 815 | return; 816 | } 817 | /* Message */ 818 | if((*msgq) == NULL) 819 | { 820 | (*msgq) = bufNew; 821 | } 822 | else 823 | { 824 | bufPtr = (*msgq); 825 | while(bufPtr->next != NULL) 826 | { 827 | bufPtr = bufPtr->next; 828 | } 829 | 830 | bufPtr->next = bufNew; 831 | } 832 | 833 | bufNew->next = NULL; 834 | } 835 | 836 | /** 837 | * [BufGet : Get Available Buffer Area] 838 | * @return [buffer] 839 | */ 840 | buffer *BufGet() 841 | { 842 | buffer *buff; 843 | 844 | buff = freebuf; 845 | freebuf = freebuf->next; 846 | 847 | return buff; 848 | } 849 | 850 | /** 851 | * [BufRemov : Remove one buffer created by sender] 852 | * @param msgq [message queue] 853 | * @param sender [sender id] 854 | * @return [buffer] 855 | */ 856 | buffer *BufRemov(buffer **msgq,int sender) 857 | { 858 | buffer *bufPtr, *bufNew; 859 | bufPtr = (*msgq); 860 | 861 | /* if the head of message queue then pop it*/ 862 | if(bufPtr->sender == sender) 863 | { 864 | bufNew = bufPtr; 865 | (*msgq) = bufNew->next; 866 | bufNew->next = NULL; 867 | return bufNew; 868 | } 869 | 870 | /* Find buffer sent by sender */ 871 | while(bufPtr->next != NULL && bufPtr->next->sender != sender) 872 | bufPtr = bufPtr->next; 873 | 874 | /* Can't find ,return null */ 875 | if(bufPtr->next == NULL) 876 | return NULL; 877 | 878 | bufNew = bufPtr->next; 879 | bufPtr->next = bufNew->next; 880 | bufNew->next = NULL; 881 | return bufNew; 882 | } 883 | /*------------------------ Buffer ----------------------- */ 884 | 885 | /*------------------------ Semaphore ----------------------- */ 886 | /** 887 | * [SemInit : init the value of semaphore ] 888 | */ 889 | void SemInit() 890 | { 891 | /* 892 | FreeBufMutexf = {1,NULL}; 893 | FreeBufNum = {MAX_BUF_NUM,NULL}; 894 | 895 | TcbMutex = {1,NULL}; 896 | TcbEmpty = {MAX_TCB_NUM,NULL}; 897 | TcbFull = {0,NULL}; 898 | */ 899 | } 900 | 901 | /** 902 | * [P : P Operation] 903 | * @param sem [semaphore pointer] 904 | */ 905 | void P(semaphore *sem) 906 | { 907 | struct TCB **blkq; 908 | disable(); 909 | 910 | sem->value--; 911 | /* There is no available resources */ 912 | if(sem->value < 0) 913 | { 914 | blkq = &(sem->wq); 915 | /* Insert current thread to Block Queue */ 916 | ThreadBlock(blkq); 917 | } 918 | enable(); 919 | } 920 | 921 | /** 922 | * [V : V operation] 923 | * @param sem [semaphore pointer] 924 | */ 925 | void V(semaphore *sem) 926 | { 927 | struct TCB **blkq; 928 | disable(); 929 | sem->value++; 930 | /* There are block threads in Block Queue */ 931 | if(sem->value <= 0) 932 | { 933 | blkq = &(sem->wq); 934 | /* Wake Up the top thread from Block Queue*/ 935 | ThreadWakeUp(blkq); 936 | } 937 | enable(); 938 | } 939 | 940 | /*------------------------ Semaphore ----------------------- */ 941 | -------------------------------------------------------------------------------- /3_Simple_File_System/README.md: -------------------------------------------------------------------------------- 1 | #Start Time 2 | 2016 May 12 3 | 4 | 5 | >备注: 重构失败 ,学长的代码是能用的。本来要赶超学长的,结果自己的代码跑都跑不起来… 6 | 工期推到暑假。到时候做一个吊炸天的文件系统。 7 | 8 | #内容要求 9 | 10 | (1) 在内存中开辟一个虚拟磁盘空间作为文件存储分区,在其上实现一个简单的基于多级目录的单用户单任务系统中的文件系统。在退出该文件系统的使用时,应将该虚拟文件系统以一个Windows 文件的方式保存到磁盘上,以便下次可以再将它恢复到内存的虚拟磁盘空间中。 11 | 12 | (2) 文件存储空间的分配可采用显式链接分配或其他的办法。 13 | 14 | (3) 空闲磁盘空间的管理可选择位示图或其他的办法。如果采用位示图来管理文件存储空间,并采用显式链接分配方式,那么可以将位示图合并到FAT中。 15 | 16 | (4) 文件目录结构采用多级目录结构。为了简单起见,可以不使用索引结点,其中的每个目录项应包含文件名、物理地址、长度等信息,还可以通过目录项实现对文件的读和写的保护。 17 | 18 | (5) 要求提供以下操作命令 19 | ####操作命令列表 20 | * my_format:对文件存储器进行格式化,即按照文件系统的结构对虚拟磁盘空间进行布局,并在其上创建根目录以及用于管理文件存储空间等的数据结构。 21 | 22 | * my_mkdir:用于创建子目录。 23 | 24 | * my_rmdir:用于删除子目录。 25 | 26 | * my_ls:用于显示目录中的内容。 27 | 28 | * my_cd:用于更改当前目录。 29 | 30 | * my_create:用于创建文件。 31 | 32 | * my_open:用于打开文件。 33 | 34 | * my_close:用于关闭文件。 35 | 36 | * my_write:用于写文件。 37 | 38 | * my_read:用于读文件。 39 | 40 | * my_rm:用于删除文件。 41 | 42 | * my_exitsys:用于退出文件系统。 43 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/Common.cpp: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | /** 4 | * 返回指向对应分区的首盘块的指针 5 | * @param VHDPtr [description] 6 | * @param blockNo [盘块号] 7 | * BOOT_BLOCK 0 8 | * FAT1 1 9 | * FAT2 3 10 | * ROOT_DIR 5 11 | * @return [description] 12 | */ 13 | unsigned char * getBlockPtrByBlockNo(unsigned char *VHDPtr,int blockNo) 14 | { 15 | return VHDPtr + VHD_BLOCK_SIZE * blockNo; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/Common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | using namespace std; 14 | 15 | 16 | /** 17 | * CONST DEFINE | 定义常量 18 | * 19 | * @Author Scorpion 20 | * 21 | */ 22 | 23 | 24 | /** 25 | * COMMON | 公用 26 | * 27 | * FALSE  :假 28 | * TRUE :真 29 | * OBJECT_NOT_FOUND : 对象没有找到 30 | */ 31 | #define FALSE 0 32 | #define TRUE 1 33 | #define SUCCESS 1 34 | #define FAILURE -1 35 | #define OBJECT_NOT_FOUND -1 36 | 37 | 38 | /** 39 | * VHD: Virtual Hard Disk 虚拟磁盘 40 | * 41 | * VHD_SIZE :虚拟磁盘的大小 42 | * VHD_BLOCK_SIZE : VHD中单个盘块的大小 43 | * VHD_BLOCK_FREE :FAT表中盘块空闲的标志 44 | * VHD_BLOCK_FILE_END :FAT 文件结束标志 45 | * VHD_BLOCK_NUM : 盘块的总数 46 | * 47 | */ 48 | #define VHD_SIZE 1024000 49 | #define VHD_BLOCK_SIZE 1024 50 | #define VHD_BLOCK_FREE 0 51 | #define VHD_BLOCK_FILE_END 65535 52 | #define VHD_BLOCK_NUM 1000 53 | 54 | /** 55 | * File System Structure | 文件系统结构 56 | * 57 | * BLOCK_INDEX_BOOT_BLOCK :引导块的首盘块号 58 | * BLOCK_INDEX_FAT1 : FAT1 的首盘块号 59 | * BLOCK_INDEX_FAT2 : FAT2 的首盘块号 60 | * BOLCK_INDEX_ROOT_DIR : 根目录文件的盘块号 61 | * 62 | */ 63 | 64 | /** 65 | * FAT File System Structure 66 | * FAT 文件系统结构 67 | * 68 | * |Start| End | Name | Note | 69 | * |-----|-----|------------|-------------------| 70 | * | 0 | 0 | Boot Block | 引导区 | 71 | * |-----|-----|------------|-------------------| 72 | * | 1 | 2 | FAT1 | 文件分配表 | 73 | * |-----|-----|------------|-------------------| 74 | * | 3 | 4 | FAT2 | 文件分配表-备份 | 75 | * |-----|-----|------------|-------------------| 76 | * | 5 | 5 | ROOT DIR | 根目录区 | 77 | * |-----|-----|------------|-------------------| 78 | * | 5 | 1000| DATA Area | 数据区 | 79 | * 80 | */ 81 | 82 | #define BLOCK_INDEX_BOOT_BLOCK 0 83 | #define BLOCK_INDEX_FAT1 1 84 | #define BLOCK_INDEX_FAT2 3 85 | #define BLOCK_INDEX_ROOT_DIR 5 86 | #define BLOCK_INDEX_DATA_AREA 5 87 | 88 | #define BLOCK_NUM_BOOT_BLOCK 1 89 | #define BLOCK_NUM_FAT 2 90 | #define BLOCK_NUM_ROOT_DIR 1 91 | 92 | 93 | /** 94 | * File Sytem + Boot Block | 文件系统 95 | */ 96 | 97 | #define MAGIC_NUM_LEN 8 98 | #define SYS_INFO_LEN 200 99 | static const char * FileSysMagicNum = "10101010"; 100 | 101 | 102 | /** 103 | * File Buffer :文件缓冲 104 | */ 105 | #define FILE_BUF_SIZE 10000 106 | 107 | 108 | /** 109 | * FCB 110 | * FILE_NAME_LEN : 文件名的长度 [Filename Extension Length] 111 | * FILE_NAME_EXTEN_LEN : 文件拓展名的长度[Filename Extension Length] 112 | * [metadata] 113 | * MD_DIR_FILE :目录文件 114 | * MD_DATA_FILE :用户数据文件 115 | */ 116 | #define FILE_NAME_LEN 8 117 | #define FILE_NAME_EXTEN_LEN 3 118 | #define MD_DIR_FILE 0 119 | #define MD_DATA_FILE 1 120 | 121 | 122 | 123 | //#define FILE_META_LEN 100 124 | 125 | 126 | /** 127 | * File Discriptor Table | 文件描述符表 128 | * 129 | * DIR_NAME_LEN : 文件目录名的长度 130 | */ 131 | #define DIR_NAME_LEN 80 132 | 133 | 134 | 135 | /** 136 | * Open File Table |用户打开文件表 137 | * 138 | * OFT_NUM : OftList的长度 139 | */ 140 | #define OFT_NUM 10 141 | 142 | 143 | 144 | /** 145 | * Data Store File | 数据存储文件TXT 146 | * 147 | * MAGIC_NUM_LEN :魔数的长度 [Magic Number Length] 148 | * FileSysMagicNum : 文件系统DATA储存文件的文件魔数 149 | * FileSysName :文件系统DATA储存文件的名称 150 | * 151 | */ 152 | static const char * FileSysName = "FileSys.txt"; 153 | 154 | 155 | /** 156 | * File Read Style | 文件写入的几种方式 157 | * 158 | * WS_REWRITE : 159 | * WS_OVERWRITE : 160 | * WS_APPEND : 追加写 161 | */ 162 | #define WS_REWRITE 0 163 | #define WS_OVERWRITE 1 164 | #define WS_APPEND 2 165 | 166 | 167 | /** 168 | * Console Command | 终端命令 169 | * CMD_NUM :命令的个数 170 | * CMD_LEN : 命令的长度 171 | * CmdGroup: 指令集 172 | */ 173 | #define CMD_NUM 15 174 | #define CMD_LEN 10 175 | static const char CmdGroup[CMD_NUM][CMD_LEN] = { 176 | "mkdir", "rmdir", "ls", "cd", "create", 177 | "rm", "open", "close", "write", 178 | "read", "exit", "help","bigfile" 179 | }; 180 | 181 | 182 | 183 | unsigned char * getBlockPtrByBlockNo(unsigned char *VHDPtr,int blockNo); 184 | 185 | #endif 186 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/FAT.cpp: -------------------------------------------------------------------------------- 1 | #include "FAT.h" 2 | 3 | 4 | void deleteFileAtFat(unsigned char *VhdPtr,int blockNo){ 5 | 6 | FAT * fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 7 | 8 | int current = blockNo; 9 | int next; 10 | while(TRUE){ 11 | next = fat1[current].id; 12 | fat1[current].id = VHD_BLOCK_FREE; 13 | if(next != VHD_BLOCK_FILE_END){ 14 | current = next; 15 | }else{ 16 | fat1[next].id = VHD_BLOCK_FREE; 17 | break; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/FAT.h: -------------------------------------------------------------------------------- 1 | #ifndef _FAT_H_ 2 | #define _FAT_H_ 3 | 4 | /** 5 | * [文件说明] 6 | * FAT : File Allocation Table 7 | * 文件分配表 8 | * 9 | */ 10 | 11 | #include "Common.h" 12 | 13 | /** 14 | * FAT : File Allocation Table 15 | */ 16 | typedef struct FAT 17 | { 18 | unsigned short id; 19 | } FAT; 20 | 21 | void deleteFileAtFat(unsigned char *VhdPtr,int blockNo); 22 | 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/FCB.cpp: -------------------------------------------------------------------------------- 1 | #include "FCB.h" 2 | 3 | 4 | /** 5 | * 设置FCB 的时间 6 | * @param fcb [description] 7 | */ 8 | void setFcbTime(FCB *fcb){ 9 | time_t rawTime = time(NULL); 10 | struct tm *time = localtime(&rawTime); 11 | /*root->time 是unsigned short int类型的数据, 32位编译器下长16位,64位编译器下长32位 12 | * 这里考虑32位编译器, 所以完整的表示一个时间的秒数是不够长的,所以,保存秒数的一半 13 | * 这样小时占5位,分钟占6位,秒占5位 14 | */ 15 | unsigned short currentTime = time->tm_hour * 2048 + time->tm_min*32 + time->tm_sec/2; 16 | 17 | /** 18 | * 年份我们保存的是实际值-2000, time->tm_mon要+1是因为,这个结构设计的时候0代表1月 19 | * 同理,年份占7位,月份占4位,日期占5位 20 | */ 21 | unsigned short currentDate = (time->tm_year-2000)*512 + (time->tm_mon+1)*32 + (time->tm_mday); 22 | 23 | fcb->createTime = currentTime; 24 | fcb->createDate = currentDate; 25 | } 26 | 27 | /** 28 | * 初始化FCB 29 | * @param fcbPtr [description] 30 | */ 31 | void initFcb(FCB *fcbPtr){ 32 | 33 | memset(fcbPtr,0,sizeof(FCB)); 34 | 35 | fcbPtr->length = 0; 36 | strcpy(fcbPtr->fileName,""); 37 | strcpy(fcbPtr->fileNameExten,""); 38 | fcbPtr->isUse = FALSE; 39 | } 40 | 41 | void initFcb(FCB * fcbPtr,char *fname,char *ename,unsigned char metadata){ 42 | 43 | initFcb(fcbPtr); 44 | 45 | strcpy(fcbPtr->fileName,fname); 46 | strcpy(fcbPtr->fileNameExten,ename); 47 | setFcbTime(fcbPtr); 48 | fcbPtr->isUse = TRUE; 49 | fcbPtr->metadata = metadata; 50 | } 51 | /** 52 | * 判断文件名是否匹配 53 | * @return [description] 54 | */ 55 | int fileNameMatch(FCB * fcbPtr,char *fname,char *ename){ 56 | 57 | if(strcmp(fcbPtr->fileName,fname) == 0 && strcmp(fcbPtr->fileNameExten,ename)==0){ 58 | return TRUE; 59 | }else{ 60 | return FALSE; 61 | } 62 | } 63 | 64 | 65 | void printDataFile(FCB *fcbPtr){ 66 | 67 | // length - 2 是因为末尾有/n和/0两个字符 68 | unsigned int length = fcbPtr->length; 69 | if(length != 0) 70 | length -= 2; 71 | printf("%s.%s\t%dB\t%d/%d/%d\t%02d:%02d:%02d\n", 72 | fcbPtr->fileName, 73 | fcbPtr->fileNameExten, 74 | length, 75 | (fcbPtr->createDate>>9)+2000, 76 | (fcbPtr->createDate>>5)&0x000f, 77 | (fcbPtr->createDate)&0x001f, 78 | (fcbPtr->createTime>>11), 79 | (fcbPtr->createTime>>5)&0x003f, 80 | (fcbPtr->createTime)&0x001f * 2); 81 | } 82 | 83 | void printDirFile(FCB *fcbPtr){ 84 | printf("%s\\\t\t%d/%d/%d\t%d:%d:%d\n", 85 | fcbPtr->fileName, 86 | (fcbPtr->createDate>>9)+2000, 87 | (fcbPtr->createDate>>5)&0x000f, 88 | (fcbPtr->createDate)&0x001f, 89 | (fcbPtr->createTime>>11), 90 | (fcbPtr->createTime>>5)&0x003f, 91 | (fcbPtr->createTime)&0x001f * 2); 92 | } 93 | 94 | 95 | int initDirectoryFile(unsigned char *VhdPtr,int blockNo,int parentBlockNo){ 96 | 97 | int fcbNum = int(VHD_BLOCK_SIZE / sizeof(FCB)); 98 | //void initFcb(FCB * fcbPtr,char *fname,char *ename,unsigned char metadata) 99 | FCB *fcbPtr = (FCB *)getBlockPtrByBlockNo(VhdPtr,blockNo); 100 | FCB *fcbPtrParent = (FCB *)getBlockPtrByBlockNo(VhdPtr,parentBlockNo); 101 | 102 | // Special File Directory Entry "." 103 | initFcb(fcbPtr,".","di",MD_DIR_FILE); 104 | fcbPtr->blockNo = blockNo; 105 | fcbPtr->length = 2 * sizeof(FCB); 106 | 107 | // Special File Directory Entry ".." 108 | fcbPtr++; 109 | initFcb(fcbPtr,"..","di",MD_DIR_FILE); 110 | fcbPtr->blockNo = parentBlockNo; 111 | //fcbPtr->length not ... 112 | 113 | return SUCCESS; 114 | /* 115 | for(int i = 2; i < fcbNum; i++,fcbPtr++){ 116 | initFcb(fcbPtr); 117 | } 118 | */ 119 | 120 | } 121 | /* Find a available directory */ 122 | int getNextFcb(FCB *fcbPtr){ 123 | 124 | int fcbNum = int(VHD_BLOCK_SIZE/sizeof(FCB)); 125 | 126 | for(int i = 2;i < fcbNum; i++,fcbPtr++){ 127 | if(fcbPtr->isUse == FALSE){ 128 | return i; 129 | } 130 | } 131 | 132 | return OBJECT_NOT_FOUND; 133 | } 134 | 135 | int initDataFileFcb(FCB *fcbPtr,char * fileName,int blockNo){ 136 | 137 | char * fname = strtok(fileName,"."); 138 | char * ename = strtok(NULL,"."); 139 | 140 | if(!ename){ 141 | cout << "Data File : file name extension could not be null " << endl; 142 | return FAILURE; 143 | } 144 | 145 | initFcb(fcbPtr,fname,ename,MD_DATA_FILE); 146 | fcbPtr->blockNo = blockNo; 147 | 148 | return TRUE; 149 | } 150 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/FCB.h: -------------------------------------------------------------------------------- 1 | #ifndef _FCB_H_ 2 | #define _FCB_H_ 3 | 4 | #include "Common.h" 5 | 6 | 7 | /** 8 | * @name 9 | * File Control Block | 文件控制块 10 | * @note 11 | * 用户存储文件的描述和控制信息的数据结构 12 | * 常用的有FCB和iNode,在FAT文件系统中使用的是FCB 13 | * 文件与文件控制块一一对应关系。 14 | *------------------------------------------------- 15 | * @name 16 | * File Directoty | 目录文件 17 | * @note 18 | * 文件控制块的有序集合,可以理解成好多个FCB的数组 19 | * 20 | * 21 | * ------------------------------------------------- 22 | * @name 23 | * File Directoty Entry| 文件的目录项 24 | * @note 25 | * 一个FCB就是一个文件目录项 26 | * 文件目录项分类: 27 | * 1. 卷标目录项 28 | * 2. "." 目录项 29 | * 3. ".."目录项 30 | * 4. 短文件名目录项* 31 | * 5. 尝文件名目录项 32 | * 33 | * 短文件名目录项是最重要的数据结构,其中存放着有关 34 | * 子目录或文件的短文件名、属性、起始簇号、时间值 35 | * 以及内容大小等信息。 36 | * @link 37 | * http://blog.csdn.net/eastonwoo/article/details/8450060 38 | * ------------------------------------------------- 39 | */ 40 | 41 | //Directory Entry , 42 | // 43 | typedef struct FCB 44 | { 45 | /** 46 | * File Name | 文件名称 47 | * @length 8B 48 | */ 49 | char fileName[FILE_NAME_LEN]; //file name 50 | 51 | /** 52 | * Filename Extension | 文件拓展名 53 | * @length 3B 54 | */ 55 | char fileNameExten[FILE_NAME_EXTEN_LEN]; // 56 | 57 | /** 58 | * Metadata | 元数据 59 | * @note 元数据[metadata] 等同于 文件属性[attribute] 60 | * 每一位代表文件是具备该属性(具备:1 不具备:0) 61 | * 目前实现的文件系统里面只用到了其中一位用于表示是数据文件还是目录文件 62 | * @length 1B 63 | * @value 64 | * MD_DATA_FILE : 数据文件 65 | * MD_DIR_FILE : 目录文件 66 | * 67 | */ 68 | unsigned char metadata; 69 | 70 | /** 71 | * Create Time | 文件创建时间 72 | * 73 | * @note 74 | * root->time 是unsigned short int类型的数据, 32位编译器下长16位,64位编译器下长32位 75 | * 这里考虑32位编译器, 所以完整的表示一个时间的秒数是不够长的,所以,保存秒数的一半 76 | * 这样小时占5位,分钟占6位,秒占5位 77 | * @value 78 | * @length 79 | * 80 | */ 81 | unsigned short createTime; 82 | 83 | /** 84 | * Create Date | 创建日期 85 | * @note 86 | * 年份我们保存的是实际值-2000, time->tm_mon要+1是因为,这个结构设计的时候0代表1月 87 | * 同理,年份占7位,月份占4位,日期占5位 88 | * @value 89 | * 90 | */ 91 | unsigned short createDate; 92 | 93 | /** 94 | * Block Number | 盘块号 95 | * @note FCB的首盘块号 96 | * @length 2B 97 | */ 98 | unsigned short blockNo; //this file's the first Block Number 99 | 100 | 101 | /** 102 | * File Length | 文件大小/长度 103 | * @length 4B 104 | */ 105 | unsigned long length; 106 | 107 | 108 | /** 109 | * Is Free | 是否被占用 110 | * @value 111 | * TRUE : 正在被使用 112 | * FALSE : FCB空闲 113 | * @length 1B 114 | */ 115 | char isUse; 116 | }FCB; 117 | 118 | void setFcbTime(FCB *fcb); 119 | void initFcb(FCB *fcbPtr); 120 | void initFcb(FCB * fcbPtr,char *fname,char *ename,unsigned char metadata); 121 | int fileNameMatch(FCB * fcbPtr,char *fname,char *ename); 122 | void printDirFile(FCB *fcbPtr); 123 | void printDataFile(FCB *fcbPtr); 124 | 125 | int initDirectoryFile(unsigned char *VhdPtr,int blockNo,int parentBlockNo); 126 | int initDataFileFcb(FCB *fcbPtr,char * fileName,int blockNo); 127 | int getNextFcb(FCB *fcbPtr); 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/FDT.cpp: -------------------------------------------------------------------------------- 1 | #include "FDT.h" 2 | 3 | FDT * initFdt(FDT* fdtPtr){ 4 | fdtPtr->filePtr = 0; 5 | fdtPtr->isUpate = FALSE; 6 | 7 | return fdtPtr; 8 | } 9 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/FDT.h: -------------------------------------------------------------------------------- 1 | #ifndef _FDT_H_ 2 | #define _FDT_H_ 3 | 4 | #include "Common.h" 5 | 6 | /** 7 | * File Discriptor Table | 文件描述符表 8 | * @note 9 | * 10 | * @wiki 11 | * 文件描述符、文件描述符表、打开文件表、目录项、索引节点之间的联系 12 | * http://www.cnblogs.com/yanenquan/p/4614805.html 13 | * 14 | */ 15 | 16 | typedef struct FDT{ 17 | 18 | /** 19 | * File Pointer | 文件读写指针 / 游标 20 | * @note 21 | * 用于记录读取的位置 22 | */ 23 | int filePtr; 24 | 25 | /** 26 | * Is Update | 是否更新 27 | * @note 28 | * FCB是否更新过 29 | * @value 30 | * TRUE : 跟新过 31 | * FALSE : 未更新 32 | */ 33 | char isUpate; //to Record the Change of FCB-> Change:TRUE 34 | 35 | /** 36 | * Parent Directory File's Block Number 37 | * @note 38 | * 当前文件的父目录文件所在的盘块号 39 | * 40 | */ 41 | int pdfBlockNo; 42 | 43 | /** 44 | * 45 | * File Directory Entry Number 46 | * @note 47 | * 当前文件的父目录文件中的目录项的序号 48 | * 即该文件在父目录文件中对应的FCB序号 49 | * @name 50 | * File Directory Entry 目录项 51 | * 参见FCB.h中的介绍 52 | */ 53 | int fdEntryNo; // Parent Dirrectory Entry Number in parentDirBlockNo 54 | 55 | /** 56 | * Directory Name | 路径名称 57 | * @demo 58 | * \root\scropion\ 59 | * @length 60 | * 80 61 | */ 62 | char dirName[DIR_NAME_LEN]; 63 | 64 | 65 | }FDT; 66 | 67 | 68 | FDT * initFdt(FDT* fdtPtr); 69 | #endif 70 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/OFT.cpp: -------------------------------------------------------------------------------- 1 | #include "OFT.h" 2 | 3 | 4 | OFT * openFile(OFT * OftList,FCB *fcbPtr){ 5 | 6 | int iOft = getNextOft(OftList); 7 | OFT *oftPtr; 8 | 9 | if(iOft == OBJECT_NOT_FOUND){ 10 | cout << "Error: Open File Table List is full.." << endl; 11 | return NULL; 12 | } 13 | 14 | 15 | oftPtr = OftList + iOft; 16 | 17 | initOftWithFcb(OftList,iOft,fcbPtr); 18 | } 19 | 20 | 21 | 22 | OFT * initOftWithFcb(OFT * OftList,int iOft,FCB *fcbPtr){ 23 | 24 | OFT * oftPtr = OftList + iOft; 25 | int pdfOftIndex; // parent directory file in openfile list 26 | // 1.Init 27 | initOft(oftPtr); 28 | loadFcb2Oft(oftPtr,fcbPtr); 29 | 30 | 31 | /* 32 | // 2.Apply for a free OFT in OftList 33 | 34 | pdfOftIndex = findPdfOft(OftList,iOft); 35 | if(pdfOftIndex == OBJECT_NOT_FOUND){ 36 | cout << "Error: OFT could not find parent directory in OftList" <fdt->pdfBlockNo = pdfOftPtr->fcb->blockNo; 43 | oftPtr->fdt->fdEntryNo = //TODO ? 44 | */ 45 | } 46 | 47 | 48 | /** 49 | * 初始化OFT 50 | * @param oft [description] 51 | * @return [description] 52 | */ 53 | OFT * initOft(OFT * oftPtr){ 54 | 55 | initFcb(&(oftPtr->fcb)); 56 | initFdt(&(oftPtr->fdt)); 57 | 58 | oftPtr->isUse = FALSE; 59 | 60 | return oftPtr; 61 | } 62 | 63 | 64 | 65 | /** 66 | * Load FCB To OFT |加载FCB中的信息到OFT中来 67 | * @param oftPtr [description] 68 | * @param fcbPtr [description] 69 | */ 70 | void loadFcb2Oft(OFT *oftPtr,FCB *fcbPtr){ 71 | // copy memory : fcb to OFT->fcb 72 | memcpy(&(oftPtr->fcb),fcbPtr,sizeof(FCB)); 73 | } 74 | 75 | /* 加载 Oft中的信息到Fcb中来 */ 76 | void loadOft2Fcb(OFT *oftPtr,FCB *fcbPtr){ 77 | memcpy(fcbPtr,&(oftPtr->fcb),sizeof(FCB)); 78 | } 79 | 80 | /** 81 | * 获取OFTList中空闲的OFT 82 | * @param OFTList [description] 83 | * @param OFTNum [description] 84 | * @return [description] 85 | */ 86 | int getNextOft(OFT * OftList){ 87 | int i; 88 | 89 | for(i = 0; i < OFT_NUM; i++){ 90 | if(OftList[i].isUse == FALSE){ 91 | OftList[i].isUse == TRUE; 92 | return i; 93 | } 94 | } 95 | 96 | return OBJECT_NOT_FOUND; 97 | } 98 | 99 | 100 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/OFT.h: -------------------------------------------------------------------------------- 1 | #ifndef _OFT_H_ 2 | #define _OFT_H_ 3 | 4 | #include "Common.h" 5 | #include "FCB.h" 6 | #include "FDT.h" 7 | /* 8 | * Open File Table | 打开文件表 9 | * @note 10 | * 打开文件表包含两部分 : 用户文件描述表 和 内存FCB表 11 | * 12 | */ 13 | typedef struct OFT 14 | { 15 | /** 16 | * File Control Block | 文件控制块 17 | */ 18 | FCB fcb; 19 | 20 | /** 21 | * File Discriptor Table | 文件描述符表 22 | */ 23 | FDT fdt; 24 | 25 | /* 26 | * Is Use |是否被占用 27 | * @note 28 | * 当前OFT是否被占用 29 | * @value 30 | * TRUE : 正在被使用 31 | * FALSE : OFT空闲 32 | */ 33 | char isUse; 34 | }OFT; 35 | 36 | 37 | OFT * addFcb2OftList(OFT * OftList,FCB *fcbPtr); 38 | OFT * initOftWithFcb(OFT * OftList,int iOft,FCB *fcbPtr); 39 | OFT * initOft(OFT * oftPtr); 40 | //int initOft(OFT *OftList,int piOft,char * filename); 41 | void loadFcb2Oft(OFT *oftPtr,FCB *fcbPtr); 42 | void loadOft2Fcb(OFT *oftPtr,FCB *fcbPtr); 43 | int getNextOft(OFT * OftList); 44 | //int getIndexOfFcb(OFT *oftPtr,char * fname,char *ename,unsigned char ftype); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/SysStructure.cpp: -------------------------------------------------------------------------------- 1 | #include "SysStructure.h" 2 | 3 | 4 | /** 5 | * Get Next VHD Block | 寻找下一个空闲的盘块 6 | * @note 7 | * 从数据区的第一个盘块开始查找 8 | * @param fatPtr [description] 9 | * @return [description] 10 | */ 11 | unsigned short int getNextVhdBlock(FAT * fatPtr){ 12 | 13 | int i; 14 | 15 | // Search In Data Area 16 | for(i =BLOCK_INDEX_DATA_AREA; i < VHD_BLOCK_NUM; i++){ 17 | if(fatPtr[i].id == VHD_BLOCK_FREE){ 18 | return i; 19 | } 20 | } 21 | 22 | return VHD_BLOCK_FILE_END; 23 | } 24 | 25 | 26 | /** 27 | * 根据盘块号获取在FAT1表中的指针 28 | * @param VHDPtr [description] 29 | * @param blockNo [description] 30 | * @return [description] 31 | */ 32 | FAT* getFatPtrByBlockNo(unsigned char *VHDPtr, int blockNo){ 33 | 34 | FAT * fat1 = (FAT *)getBlockPtrByBlockNo(VHDPtr,BLOCK_INDEX_FAT1); 35 | return fat1 + blockNo; 36 | } 37 | 38 | 39 | /** 40 | * Find Parent Directory File Open File‘s index in OFTList 41 | * @note 42 | * 寻找当前打开文件的父目录文件的OFT在OftList中的序号 43 | * @param OftList [description] 44 | * @param oftNum [description] 45 | * @param iOft [description] 46 | * @return [description] 47 | */ 48 | int findPdfOft(OFT *OftList,int iOft){ 49 | 50 | int i; 51 | for(i = 0; i < OFT_NUM; i++){ 52 | if(OftList[i].fcb.blockNo == OftList[iOft].fdt.pdfBlockNo){ 53 | return i; 54 | } 55 | } 56 | return OBJECT_NOT_FOUND; 57 | } 58 | 59 | 60 | 61 | /** 62 | * 初始化引导块 63 | * @param VhdPtr [description] 64 | * @return [description] 65 | */ 66 | BootBlock * initBootBlock(unsigned char *VhdPtr){ 67 | 68 | char * sysInfoStr = "文件系统,外存分配方式:FAT12,\n磁盘空间管理:结合于FAT的位示图,\n目录结构:单用户多级目录结构."; 69 | //get Boot Block 70 | unsigned char * bootBlockPtr = getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_BOOT_BLOCK); 71 | BootBlock * bootBlock = (BootBlock *)bootBlockPtr; 72 | 73 | //assign the value of Boot Block 74 | strcpy(bootBlock->magicNum,FileSysMagicNum); 75 | strcpy(bootBlock->sysInfo,sysInfoStr); 76 | bootBlock->rootBlockNo = BLOCK_INDEX_ROOT_DIR; 77 | bootBlock->dataBlockPtr = getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_DATA_AREA); 78 | 79 | return bootBlock; 80 | } 81 | 82 | /** 83 | * Init FAT1 | 初始化FAT1 84 | */ 85 | FAT * initFAT1(unsigned char *VhdPtr){ 86 | 87 | FAT *fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 88 | 89 | int i; 90 | 91 | /** 92 | * 下列盘块对应的FAT表中的值设置为 文件结束标志 93 | * |Start| End | Name | Note | 94 | * |-----|-----|------------|-------------------| 95 | * | 0 | 0 | Boot Block | 引导区 | 96 | * |-----|-----|------------|-------------------| 97 | * | 1 | 2 | FAT1 | 文件分配表 | 98 | * |-----|-----|------------|-------------------| 99 | * | 3 | 4 | FAT2 | 文件分配表-备份 | 100 | * |-----|-----|------------|-------------------| 101 | */ 102 | for(i = BLOCK_INDEX_BOOT_BLOCK;i < BLOCK_INDEX_DATA_AREA; i++){ 103 | fat1[i].id = VHD_BLOCK_FILE_END; 104 | } 105 | 106 | /** 107 | * 下列数据区的盘块对应的FAT表中的值设置为 FREE 108 | * |-----|-----|------------|-------------------| 109 | * | 5 | 1000| DATA Area | 数据区 | 110 | * |-----|-----|------------|-------------------| 111 | */ 112 | for(i = BLOCK_INDEX_DATA_AREA;i < VHD_BLOCK_NUM; i++){ 113 | 114 | fat1[i].id = VHD_BLOCK_FREE; 115 | } 116 | 117 | fat1[BLOCK_INDEX_ROOT_DIR].id = VHD_BLOCK_FILE_END; 118 | 119 | return fat1; 120 | } 121 | 122 | /** 123 | * Init FAT2 | 初始化FAT2 124 | * @note 125 | * 126 | * @param VhdPtr [description] 127 | */ 128 | void initFAT2(unsigned char *VhdPtr){ 129 | FAT * fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 130 | FAT * fat2 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT2); 131 | memcpy(fat2,fat1,VHD_BLOCK_SIZE *2); 132 | } 133 | 134 | /** 135 | * 初始化根目录[Root Directory]的FCB 136 | * 137 | * 初始化的根目录 只有两个FCB 138 | * 1. fcbDot 139 | * "." 当前目录 140 | * 141 | * length : 2 * fcb 142 | * 2. fcbDotDot 143 | * ".." 上一级目录 比较特殊在这里指向自己 144 | * 3. 其他空白PCB 145 | * @param VhdPtr [description] 146 | * @return [description] 147 | */ 148 | void initRootDirBlock(unsigned char *VhdPtr){ 149 | //FCB * rootPtr = (FCB *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_ROOT_DIR); 150 | 151 | initDirectoryFile(VhdPtr,BLOCK_INDEX_ROOT_DIR,BLOCK_INDEX_ROOT_DIR); 152 | 153 | } 154 | 155 | 156 | /** 157 | * 初始化根目录的OFT 158 | * @param VhdPtr [description] 159 | * @param OftList [description] 160 | * @return [description] 161 | */ 162 | OFT * initRootDirOft(unsigned char* VhdPtr,OFT * OftList){ 163 | 164 | //OftList[0] use to Store Root FCB 165 | OFT * oftPtr = OftList; 166 | 167 | FCB * fcbPtr =(FCB *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_ROOT_DIR); 168 | 169 | initOft(oftPtr); 170 | loadFcb2Oft(oftPtr,fcbPtr); 171 | strcpy(oftPtr->fdt.dirName,"\\root\\"); 172 | 173 | oftPtr->fdt.pdfBlockNo = BLOCK_INDEX_ROOT_DIR; //5 174 | oftPtr->fdt.fdEntryNo = 0; //Root Dir 的父目录文件就是自己 目录项为首个FCB . 175 | 176 | return oftPtr; 177 | } 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/SysStructure.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYS_STRUCTURE_H_ 2 | #define _SYS_STRUCTURE_H_ 3 | 4 | #include "Common.h" 5 | #include "FAT.h" 6 | #include "FCB.h" 7 | #include "FDT.h" 8 | #include "OFT.h" 9 | 10 | 11 | /** 12 | * FAT File System Structure 13 | * FAT 文件系统结构 14 | * 15 | * |Start| End | Name | Note | 16 | * |-----|-----|------------|-------------------| 17 | * | 0 | 0 | Boot Block | 引导区 | 18 | * |-----|-----|------------|-------------------| 19 | * | 1 | 2 | FAT1 | 文件分配表 | 20 | * |-----|-----|------------|-------------------| 21 | * | 3 | 4 | FAT2 | 文件分配表-备份 | 22 | * |-----|-----|------------|-------------------| 23 | * | 5 |1000 | DATA BLOCK| 数据区 | 24 | * |-----|-----|------------|-------------------| 25 | * | 5 | 5 | ROOT_DIR | 根目录文件 | 26 | * 27 | */ 28 | 29 | /* 30 | * Boot Block | 引导块 31 | * 32 | * @note 33 | * 引导块占用第0号物理块,不属于文件系统管辖, 34 | * 如果系统中有多个文件系统,只有根文件系统才 35 | * 有引导程序放在引导块中,其余文件系统都不 36 | * 使用引导块 37 | * 38 | */ 39 | typedef struct BootBlock 40 | { 41 | /** 42 | * Magic Number | 魔数 43 | * 44 | * @value 45 | * 10101010 46 | */ 47 | char magicNum[MAGIC_NUM_LEN]; 48 | 49 | /** 50 | * System Information | 系统信息 51 | */ 52 | char sysInfo[SYS_INFO_LEN]; 53 | 54 | /** 55 | * Root Directory Block Number |根目录文件的盘块号 56 | */ 57 | unsigned short rootBlockNo; 58 | 59 | /** 60 | * Data Area VHD Block Pointer | 指向数据区首盘块的指针 61 | * 62 | */ 63 | unsigned char *dataBlockPtr; 64 | 65 | }BootBlock; 66 | 67 | 68 | 69 | /** 70 | * Get Next VHD Block | 寻找下一个空闲的盘块 71 | * @note 72 | * 从数据区的第一个盘块开始查找 73 | * @param fatPtr [description] 74 | * @return [description] 75 | */ 76 | unsigned short int getNextVhdBlock(FAT * fatPtr); 77 | /** 78 | * 获取OFTList中空闲的OFT 79 | * @param OFTList [description] 80 | * @param OFTNum [description] 81 | * @return [description] 82 | */ 83 | //int getNextOft(OFT * OftList); 84 | 85 | /** 86 | * 根据盘块号获取在FAT1表中的指针 87 | * @param VHDPtr [description] 88 | * @param blockNo [description] 89 | * @return [description] 90 | */ 91 | FAT* getFatPtrByBlockNo(unsigned char *VHDPtr, int blockNo); 92 | 93 | /** 94 | * Find Parent Directory File Open File‘s index in OFTList 95 | * @note 96 | * 寻找当前打开文件的父目录文件的OFT在OftList中的序号 97 | * @param OftList [description] 98 | * @param oftNum [description] 99 | * @param iOft [description] 100 | * @return [description] 101 | */ 102 | int findPdfOft(OFT *OftList,int iOft); 103 | 104 | /** 105 | * 初始化引导块 106 | * @param VhdPtr [description] 107 | * @return [description] 108 | */ 109 | BootBlock * initBootBlock(unsigned char *VhdPtr); 110 | 111 | /** 112 | * Init FAT1 | 初始化FAT1 113 | */ 114 | FAT * initFAT1(unsigned char *VhdPtr); 115 | 116 | 117 | /** 118 | * Init FAT2 | 初始化FAT2 119 | * @note 120 | * 121 | * @param VhdPtr [description] 122 | */ 123 | void initFAT2(unsigned char *VhdPtr); 124 | 125 | /** 126 | * 初始化根目录[Root Directory]的FCB 127 | * 128 | * 初始化的根目录 只有两个FCB 129 | * 1. fcbDot 130 | * "." 当前目录 131 | * 132 | * length : 2 * fcb 133 | * 2. fcbDotDot 134 | * ".." 上一级目录 比较特殊在这里指向自己 135 | * 3. 其他空白PCB 136 | * @param VhdPtr [description] 137 | * @return [description] 138 | */ 139 | void initRootDirBlock(unsigned char *VhdPtr); 140 | 141 | /** 142 | * 初始化根目录的OFT 143 | * @param VhdPtr [description] 144 | * @param OftList [description] 145 | * @return [description] 146 | */ 147 | OFT * initRootDirOft(unsigned char* VhdPtr,OFT * OftList); 148 | 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.1/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | 3 | #include "FAT.h" 4 | #include "FCB.h" 5 | #include "FDT.h" 6 | #include "OFT.h" 7 | #include "SysStructure.h" 8 | #include "main.h" 9 | 10 | /** 11 | * @Author Scorpion 12 | */ 13 | /*VHD: Virtual Hard Disk */ 14 | unsigned char *VhdPtr; 15 | unsigned char VhdBuffer[VHD_SIZE]; 16 | unsigned char *VhdDataBlockPtr; //the start position of data block for VHD 17 | 18 | /*OFT:Open File Table*/ 19 | OFT OftList[OFT_NUM]; 20 | int currOftIndex = 0; 21 | 22 | 23 | 24 | int main(){ 25 | cout << "File System |¡¡2016/05/23" << endl; 26 | my_start_sys(); 27 | cout << "Start System" < ",OftList[currOftIndex].fdt.dirName); 37 | gets(cmdLine); 38 | 39 | excuteCmd(cmdLine); 40 | } 41 | 42 | return 0; 43 | } 44 | 45 | /** 46 | * 初始化 47 | */ 48 | void my_format(){ 49 | 50 | initBootBlock(VhdPtr); 51 | initFAT1(VhdPtr); 52 | initFAT2(VhdPtr); 53 | initRootDirBlock(VhdPtr); 54 | saveVhdFile(VhdPtr); 55 | } 56 | 57 | /** 58 | * 开启文件系统 59 | */ 60 | void my_start_sys(){ 61 | 62 | VhdPtr = (unsigned char *)malloc(VHD_SIZE); 63 | 64 | readVhdFile(VhdPtr); 65 | 66 | initRootDirOft(VhdPtr,OftList); 67 | 68 | // Get Boot Block 69 | BootBlock * bootBlock = (BootBlock *)(getBlockPtrByBlockNo(VhdPtr,BLOCK_NUM_BOOT_BLOCK)); 70 | //Read Data Block Ptr From Boot Block 71 | VhdDataBlockPtr = bootBlock->dataBlockPtr; 72 | 73 | //Set Current OFT is this OFT: OftList 74 | currOftIndex = 0; 75 | } 76 | 77 | 78 | /** 79 | * Exit System | 退出系统 80 | * @note 81 | * 82 | */ 83 | void my_exit_sys(){ 84 | 85 | while(currOftIndex){ 86 | // TODO 87 | my_close(currOftIndex); 88 | } 89 | 90 | saveVhdFile(VhdPtr); 91 | } 92 | 93 | 94 | int my_cd(char *dirname){ 95 | if(OftList[currOftIndex].fcb.metadata == MD_DATA_FILE){ 96 | cout << " Data file can not be cd" << endl; 97 | return FAILURE; 98 | } 99 | 100 | OFT *oftPtr = OftList + currOftIndex; 101 | char *buffer = (char *)malloc(FILE_BUF_SIZE); 102 | FCB *fcbPtr = (FCB *)buffer; 103 | 104 | int fcbNum = int(oftPtr->fcb.length/sizeof(FCB)); 105 | 106 | // 遍历目录文件 查看该目录文件下 dirname匹配的目录文件是否存在 107 | int i; 108 | for(i=0;i < fcbNum;i++,fcbPtr++){ 109 | if(fileNameMatch(fcbPtr,dirname,(char *)"di")==TRUE && fcbPtr->metadata == MD_DIR_FILE){ 110 | break; 111 | } 112 | } 113 | 114 | if(i == fcbNum){ 115 | cout << "Error : No Such Directory Here ..."<< endl; 116 | return FAILURE; 117 | } 118 | 119 | if(strcmp(fcbPtr->fileName,".") == 0){ 120 | // 特殊目录项 "." 121 | return SUCCESS; 122 | } 123 | else if(strcmp(fcbPtr->fileName,"..") == 0){ // 特殊目录项 ".." 124 | if(currOftIndex == 0){ //如果是根目录文件 125 | return SUCCESS; 126 | }else{ 127 | currOftIndex = my_close(currOftIndex); 128 | } 129 | } 130 | else{ 131 | //普通文件 132 | int iOft = getNextOft(OftList); 133 | 134 | if(iOft == OBJECT_NOT_FOUND){ 135 | cout << "Error : No enough OFT " << endl; 136 | return FAILURE; 137 | } 138 | OFT * oftPtrChild = OftList + iOft; 139 | // FCB Part 140 | loadFcb2Oft(oftPtrChild,fcbPtr); 141 | // FDT Part 142 | oftPtrChild->fdt.filePtr = 0; 143 | oftPtrChild->fdt.isUpate = FALSE; 144 | 145 | //c_str() 函数的作用就是将string类型转换成char * 146 | strcpy(oftPtrChild->fdt.dirName,(string(oftPtr->fdt.dirName) + string(dirname) + string("\\")).c_str()); 147 | oftPtrChild->isUse = TRUE; 148 | oftPtrChild->fdt.pdfBlockNo = oftPtr->fcb.blockNo; 149 | oftPtrChild->fdt.fdEntryNo = i; 150 | currOftIndex = iOft; 151 | } 152 | return TRUE; 153 | } 154 | 155 | int my_ls(){ 156 | 157 | OFT *oftPtr = OftList + currOftIndex; 158 | if(oftPtr->fcb.metadata == MD_DATA_FILE){ 159 | cout << "current file is data file, can not be ls" << endl; 160 | return FALSE; 161 | } 162 | 163 | char buffer[FILE_BUF_SIZE]; 164 | oftPtr->fdt.filePtr = 0; 165 | do_read(oftPtr,oftPtr->fcb.length,buffer); 166 | 167 | FCB * fcbPtr = (FCB *)buffer; 168 | int i; 169 | int fcbNum = int(oftPtr->fcb.length/sizeof(FCB)); 170 | 171 | for(i=0;iisUse == TRUE){ 173 | if(fcbPtr->metadata == MD_DIR_FILE){ 174 | printDirFile(fcbPtr); 175 | } 176 | else if(fcbPtr->metadata == MD_DATA_FILE){ 177 | printDataFile(fcbPtr); 178 | } 179 | } 180 | } 181 | return SUCCESS; 182 | } 183 | 184 | int my_mkdir(char *dirname){ 185 | 186 | char *fname = strtok(dirname,"."); 187 | char *ename = strtok(NULL,"."); 188 | 189 | int blockNo; 190 | FAT* fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 191 | 192 | if(ename){ 193 | cout << "Error: directory file could not have file name extension."<< endl; 194 | return FAILURE; 195 | } 196 | 197 | 198 | char buffer[FILE_BUF_SIZE]; 199 | 200 | OFT * oftPtr = OftList+ currOftIndex; 201 | 202 | oftPtr->fdt.filePtr = 0; 203 | // load data to buffer 204 | do_read(oftPtr,oftPtr->fcb.length,buffer); 205 | 206 | int fcbNum = int(oftPtr->fcb.length/sizeof(FCB)); 207 | FCB * fcbPtr = (FCB *)buffer; 208 | for(int i=0;i < fcbNum;i++,fcbPtr++){ 209 | if(fileNameMatch(fcbPtr,fname,ename) && fcbPtr->metadata == MD_DIR_FILE){ 210 | cout << "Error: Directory Already Exist " << endl; 211 | return FAILURE; 212 | } 213 | } 214 | 215 | // 申请OFT 216 | int iOft = getNextOft(OftList); 217 | if(iOft == OBJECT_NOT_FOUND){ 218 | cout << "Error:No enough OFT Exist" << endl; 219 | return FAILURE; 220 | } 221 | // 申请存储的盘块 222 | blockNo = getNextVhdBlock(fat1); 223 | if(blockNo == VHD_BLOCK_FILE_END){ 224 | cout << "Error: No Free Block Exist " << endl; 225 | //若失败 释放申请的OFT 226 | OftList[iOft].isUse = FALSE; 227 | return FAILURE; 228 | } 229 | 230 | fat1[blockNo].id = VHD_BLOCK_FILE_END; 231 | initFAT2(VhdPtr); 232 | 233 | // 在父目录下寻找空闲的FCB 234 | int i; 235 | for(i=0;iisUse == FALSE){ 237 | break; 238 | } 239 | } 240 | 241 | oftPtr->fdt.filePtr = i*sizeof(FCB); 242 | oftPtr->fdt.isUpate = TRUE; 243 | // # 244 | // ÐÞ¸Äн¨µÄFCBÖеÄÄÚÈÝ 245 | FCB * fcbTmp = new FCB; 246 | initFcb(fcbTmp,dirname,(char *)"di",MD_DIR_FILE); 247 | fcbTmp->blockNo = blockNo; 248 | fcbTmp->length = 2*sizeof(FCB);\ 249 | 250 | //do_write Ç¿fcbTmpдÈ뵽Ŀ¼ÎļþÀïÃæ 251 | do_write(oftPtr,(char*)fcbTmp,sizeof(FCB),WS_OVERWRITE); /*TODO Bug!!*/ 252 | 253 | 254 | //ÉèÖôò¿ª±íÏî-Dot 255 | OFT * oftPtrChild = OftList+iOft; 256 | loadFcb2Oft(oftPtrChild,fcbTmp); 257 | strcpy(fcbTmp->fileName,"."); 258 | oftPtrChild ->fdt.filePtr = 0; 259 | do_write(oftPtrChild,(char *)fcbTmp,sizeof(FCB),WS_OVERWRITE); 260 | 261 | // fcbTmp -> Dot Dot 262 | loadOft2Fcb(oftPtr,fcbTmp); 263 | strcpy(fcbTmp->fileName,".."); 264 | oftPtrChild ->fdt.filePtr = 1*sizeof(FCB); 265 | do_write(oftPtrChild,(char *)fcbTmp,sizeof(FCB),WS_OVERWRITE); 266 | 267 | 268 | my_close(iOft); 269 | 270 | 271 | 272 | // ¸üÐÂcurrent OFT (¸¸)Ŀ¼ÎļþµÄFCB 273 | fcbPtr = (FCB *)buffer; 274 | fcbPtr->length = oftPtr->fcb.length; 275 | oftPtr->fdt.filePtr = 0; 276 | do_write(oftPtr,(char *)fcbPtr,sizeof(FCB),WS_OVERWRITE); 277 | oftPtr->fdt.isUpate = TRUE; 278 | 279 | delete fcbTmp; 280 | 281 | return SUCCESS; 282 | } 283 | 284 | int my_rmdir(char *dirname){ 285 | 286 | char * fname = strtok(dirname,"."); 287 | char * ename = strtok(NULL,"."); 288 | 289 | if(strcmp(dirname,".") == 0 && strcmp(dirname,"..") == 0){ 290 | cout << "ÌØÊâĿ¼Ïî ²»¿É±»É¾³ý" << endl; 291 | return FAILURE; 292 | } 293 | 294 | if(ename){ 295 | cout << "·Ç·¨Ä¿Â¼ÎļþÃû³Æ" << endl; 296 | return FAILURE; 297 | } 298 | 299 | char buffer[FILE_BUF_SIZE]; 300 | OFT * oftPtr = OftList + currOftIndex; 301 | oftPtr->fdt.filePtr = 0; 302 | 303 | do_read(oftPtr,oftPtr->fcb.length,buffer); 304 | 305 | int i; 306 | FCB *fcbPtr = (FCB *)buffer; 307 | 308 | int fcbNum = int(oftPtr->fcb.length /sizeof(FCB)); 309 | //ѰÕÒÕâ¸öÃû×ÖµÄĿ¼Ïî 310 | for(i = 0; i < fcbNum; i++,fcbPtr++){ 311 | if(fileNameMatch(fcbPtr,fname,(char *)"di")){ 312 | break; 313 | } 314 | } 315 | 316 | if(i == fcbNum){ 317 | cout << "ûÓÐÕâ¸öĿ¼Îļþ" << endl; 318 | return FAILURE; 319 | } 320 | 321 | // Åжϵ±Ç°Îļþ¼ÐÊÇ·ñΪ¿Õ 322 | if(fcbPtr->length > 2*sizeof(FCB)){ 323 | cout << "Ŀ¼Îļþ²»Îª¿Õ£¬ÇëÏÈɾ³ýÎļþ" << endl; 324 | return FAILURE; 325 | } 326 | 327 | int blockNo = fcbPtr->blockNo; 328 | // Çå¿ÕÕâ¸öĿ¼ÏîÕ¼¾ÝµÄFAT 329 | deleteFileAtFat(VhdPtr,blockNo); 330 | initFAT2(VhdPtr); 331 | // Çå¿Õµ±Ç°µÄFCB 332 | initFcb(fcbPtr); 333 | 334 | oftPtr->fdt.filePtr = i*sizeof(FCB); 335 | do_write(oftPtr,(char *)fcbPtr,sizeof(FCB),WS_OVERWRITE); 336 | oftPtr->fcb.length -= sizeof(FCB); 337 | 338 | // ¸üÐÂĿ¼Ïî"."ÖеÄÄÚÈÝ 339 | fcbPtr = (FCB *)buffer; 340 | fcbPtr->length = oftPtr->fcb.length; 341 | oftPtr->fdt.filePtr = 0; 342 | do_write(oftPtr,(char *)fcbPtr,sizeof(FCB),WS_OVERWRITE); 343 | 344 | oftPtr->fdt.isUpate = FALSE; 345 | 346 | return SUCCESS; 347 | } 348 | 349 | 350 | int my_create(char *filename,unsigned char metadata){ 351 | 352 | /* 353 | int i; 354 | char buffer[FILE_BUF_SIZE]; 355 | 356 | char *fname = strtok(filename,"."); 357 | char *ename = strtok(NULL,"."); 358 | 359 | FAT * fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 360 | 361 | // ÅжÏÎļþÃûÊÇ·ñºÏ·¨ 362 | if(strcmp(fname,"") == 0){ 363 | cout << "Please Input File Name" <fdt.filePtr = 0; 374 | do_read(oftPtr,oftPtr->fcb.length,buffer); 375 | FCB * fcbPtr = (FCB *)buffer; 376 | 377 | // ¼ì²éÊÇ·ñÓÐÎļþÖØÃû 378 | int fcbNum = int(oftPtr->fcb.length / sizeof(FCB)); 379 | for(i=0; i < fcbNum;i++, fcbPtr++){ 380 | if(fileNameMatch(fcbPtr,fname,ename)){ 381 | cout << "File Already Exist " <isUse == FALSE){ 391 | break; 392 | } 393 | } 394 | // TODO check if i == fcbNum 395 | //ÉêÇë¿ÕÏеÄÅÌ¿é 396 | int blockNo = getNextVhdBlock(fat1); 397 | if(blockNo == OBJECT_NOT_FOUND){ 398 | return FAILURE; 399 | } 400 | // ¸üÐÂFATÐÅÏ¢²¢Í¬²½FAT2 401 | fat1[blockNo].id = VHD_BLOCK_FILE_END; 402 | initFAT2(VhdPtr); 403 | 404 | // ÌîÈëfcbµÄÐÅÏ¢ 405 | initFcb(fcbPtr,fname,ename,MD_DATA_FILE); 406 | oftPtr->fdt.filePtr = i * sizeof(FCB); 407 | // дÈ뵱ǰĿ¼ÏîµÄÐÅÏ¢ 408 | do_write(oftPtr,(char *)fcbPtr,sizeof(FCB),WS_OVERWRITE); 409 | 410 | //Ð޸ĵ±Ç° "." Ŀ¼Ïî 411 | fcbPtr = (FCB *)buffer; 412 | fcbPtr->length = oftPtr->fcb.length; 413 | oftPtr->fdt.filePtr = 0; 414 | do_write(oftPtr,(char *)fcbPtr,sizeof(FCB),WS_OVERWRITE); 415 | 416 | oftPtr->fdt.isUpate = TRUE; 417 | 418 | */ 419 | 420 | 421 | FAT * fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 422 | OFT *pOftPtr = OftList + currOftIndex; 423 | 424 | // Apply Available FCB In Parent Directory File 425 | FCB * fcbPtr =(FCB *)getBlockPtrByBlockNo(VhdPtr,pOftPtr->fcb.blockNo); 426 | int offset = getNextFcb(fcbPtr); 427 | if(offset == OBJECT_NOT_FOUND){ 428 | cout << "Error: No Available Directory Entry" << endl; 429 | return FAILURE; 430 | } 431 | 432 | // Apply for Disk Block 433 | int blockNo = getNextVhdBlock(fat1); 434 | if(blockNo == OBJECT_NOT_FOUND){ 435 | cout << "Error : No Available Block" << endl; 436 | return FAILURE; 437 | } 438 | 439 | // Update Fat Table 440 | fat1[blockNo].id = VHD_BLOCK_FILE_END; 441 | initFAT2(VhdPtr); 442 | // Init Fcb 443 | initDataFileFcb(fcbPtr+offset,filename,blockNo); 444 | 445 | 446 | int i = initOftByFileName(OftList,currOftIndex,filename,metadata); 447 | if(i == FAILURE){ 448 | cout << "Error : No Available OFT" << endl; 449 | return FAILURE; 450 | }else{ 451 | my_close(i); 452 | } 453 | 454 | return SUCCESS; 455 | 456 | } 457 | 458 | 459 | int my_rm(char *filename){ 460 | // TODO strtok 461 | char *fname = strtok(filename,"."); 462 | char *ename = strtok(NULL,"."); 463 | 464 | if(!ename){ 465 | cout << "Error: Please Input " << endl; 466 | return FAILURE; 467 | } 468 | 469 | if(strcmp(ename,"di") == 0){ 470 | cout << "Error: File Directory can not be rm" << endl; 471 | return FAILURE; 472 | } 473 | 474 | //¶ÁÈ¡µ±Ç°µÄĿ¼Îļþµ½buffer 475 | OFT * oftPtr = OftList + currOftIndex; 476 | oftPtr->fdt.filePtr = 0; 477 | char buffer[FILE_BUF_SIZE]; 478 | do_read(oftPtr,oftPtr->fcb.length,buffer); 479 | 480 | //ѰÕÒÕâ¸öÃû×ÖµÄĿ¼Ïî 481 | int i; 482 | FCB * fcbPtr = (FCB *)buffer; 483 | int fcbNum = int(oftPtr->fcb.length / sizeof(FCB)); 484 | for(i = 0; i < fcbNum; i++,fcbPtr++){ 485 | if(strcmp(fcbPtr->fileName,fname)==0&&strcmp(fcbPtr->fileNameExten,ename)==0){ 486 | break; 487 | } 488 | } 489 | if( i == fcbNum){ 490 | cout << "No such file exist " << endl; 491 | return FAILURE; 492 | } 493 | 494 | // Çå¿ÕĿ¼ÏîÕ¼¾ÝµÄFAT 495 | deleteFileAtFat(VhdPtr,fcbPtr->blockNo); 496 | 497 | // ͬ²½FAT2 498 | initFAT2(VhdPtr); 499 | 500 | //½«µ±Ç°Ä¿Â¼ÎļþϵÄfcbPtrÖÃ¿Õ 501 | initFcb(fcbPtr); 502 | 503 | // ½«filePtrÖеÄÄÚÈÝдµ½OFTÉÏ 504 | oftPtr->fdt.filePtr = i * sizeof(FCB); 505 | oftPtr->fcb.length -= sizeof(FCB); 506 | do_write(oftPtr,(char *)fcbPtr,sizeof(FCB),WS_OVERWRITE); 507 | 508 | 509 | // ¸üÐÂĿ¼Ïî "." µÄ³¤¶È 510 | fcbPtr = (FCB *)buffer; 511 | fcbPtr->length = oftPtr->fcb.length; 512 | oftPtr->fdt.filePtr = 0; // Point to the start of the directory file 513 | do_write(oftPtr,(char *)fcbPtr,sizeof(FCB),WS_OVERWRITE); 514 | 515 | oftPtr->fdt.isUpate = TRUE; 516 | 517 | return SUCCESS; 518 | } 519 | 520 | /** 521 | * 522 | * 523 | */ 524 | int my_open(char *filename){ 525 | 526 | 527 | int i = initOftByFileName(OftList,currOftIndex,filename,MD_DATA_FILE); 528 | 529 | if(i == FAILURE){ 530 | return FAILURE; 531 | } 532 | else { 533 | currOftIndex = i; 534 | return SUCCESS; 535 | } 536 | 537 | } 538 | 539 | /** 540 | * Close File 541 | * my_close(OFT* oft); 542 | * @param iOft [description] 543 | * @return [description] 544 | */ 545 | int my_close(int iOft) 546 | { 547 | if(iOft > OFT_NUM || iOft < 0){ 548 | cout << "Error : No such file exist.." << endl; 549 | return EXIT_FAILURE; 550 | } 551 | else{ 552 | // piOft : prarent index of OFT 553 | int piOft = findPdfOft(OftList,iOft); 554 | if(piOft == OBJECT_NOT_FOUND){ 555 | cout << "Father Directory is not exist" <Buffer->Change Buffer -> Parent OFT 561 | if(OftList[iOft].fdt.isUpate == TRUE){ 562 | // load parent directory file to buffer 563 | char buffer[FILE_BUF_SIZE]; 564 | do_read(&(OftList[piOft]),OftList[piOft].fcb.length,buffer); 565 | 566 | // point to child file's file directory entry in parent directory file 567 | FCB * fcbPtr = (FCB *)(buffer + sizeof(FCB) * OftList[iOft].fdt.fdEntryNo); 568 | loadOft2Fcb(OftList+iOft,fcbPtr); 569 | OftList[piOft].fdt.filePtr = OftList[iOft].fdt.fdEntryNo * sizeof(FCB); 570 | do_write(OftList+piOft,(char *)fcbPtr,sizeof(FCB),WS_OVERWRITE); 571 | 572 | } 573 | 574 | initOft(OftList+iOft); 575 | currOftIndex = piOft; 576 | 577 | return piOft; 578 | } 579 | } 580 | 581 | 582 | 583 | int my_read(int iOft){ 584 | 585 | //²é¿´OftµÄË÷ÒýºÅÊÇ·ñºÏ·¨ 586 | if(iOft > OFT_NUM || iOft < 0){ 587 | cout << "Error : No such file exist.." << endl; 588 | return FAILURE; 589 | } 590 | 591 | OFT * oftPtr = OftList + iOft; 592 | 593 | OftList[iOft].fdt.filePtr = 0; 594 | char text[FILE_BUF_SIZE] = "\0"; 595 | do_read(oftPtr,oftPtr->fcb.length,text); 596 | 597 | //OUTPUT 598 | cout << text; 599 | return SUCCESS; 600 | } 601 | 602 | int my_write(int iOft){ 603 | 604 | //²é¿´OftµÄË÷ÒýºÅÊÇ·ñºÏ·¨ 605 | if(iOft > OFT_NUM || iOft < 0){ 606 | cout << "Error : No such file exist.." << endl; 607 | return FAILURE; 608 | } 609 | 610 | OFT * oftPtr = OftList + iOft; 611 | int wstyle; 612 | 613 | cout << "Please Choose Write Style " << endl; 614 | cout << "ÊäÈë 0 = ½Ø¶Ïд£¬1=¸²¸Çд£¬2=×·¼Óд" << endl; 615 | cin >> wstyle; 616 | if(wstyle > 2 || wstyle < 0){ 617 | cout << "Error: wrong wstyle " << endl; 618 | return FAILURE; 619 | } 620 | 621 | char text[FILE_BUF_SIZE] = "\0"; 622 | char textTmp[100] = "\0"; // MAX 100 character per line 623 | 624 | cout << "ÿÐÐ×î´ó³¤¶È£º100 »Ø³µ»»ÐУ¬ÊäÈë½áÊø£ºctrl+z" << endl; 625 | getchar(); 626 | while(gets(textTmp)){ 627 | strcat(text,textTmp); 628 | } 629 | //+1ÊÇÒòΪҪ°Ñ½áβµÄ\0Ҳд½øÈ¥ 630 | do_write(oftPtr,text,strlen(text)+1,wstyle); 631 | oftPtr->fdt.isUpate = TRUE; 632 | return SUCCESS; 633 | } 634 | 635 | 636 | 637 | /** 638 | * 639 | */ 640 | int do_read(OFT* oftPtr,int len,char *text){ 641 | 642 | int lenToRead = len; 643 | int offset = oftPtr->fdt.filePtr; // offset £ºÆ«ÒÆÁ¿ 644 | int blockNo = oftPtr->fcb.blockNo; // ÅÌ¿éºÅ 645 | FAT * fatPtr = getFatPtrByBlockNo(VhdPtr,blockNo); 646 | unsigned char * blockPtr; 647 | /* file buffer : load the whole block then next...*/ 648 | unsigned char * fileBuf = getBlockBuffer(); 649 | 650 | // offset point to another block -> turn to next block 651 | while(offset >= VHD_BLOCK_SIZE){ 652 | offset -= VHD_BLOCK_SIZE; 653 | blockNo = fatPtr->id; //index to 654 | 655 | if(blockNo == VHD_BLOCK_FILE_END){ 656 | cout << "Error: do_read no such block..." << endl; 657 | 658 | return EXIT_FAILURE; 659 | } 660 | 661 | fatPtr = getFatPtrByBlockNo(VhdPtr,blockNo); 662 | } 663 | 664 | blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 665 | 666 | // Read File To Buffer |ÏȽ«µ±Ç°ÅÌ¿é¼ÓÔØµ½BufferÖÐ 667 | memcpy(fileBuf,blockPtr,VHD_BLOCK_SIZE); 668 | 669 | 670 | char * textPtr = text; 671 | 672 | while(len > 0){ 673 | 674 | //ÐèÒª¶ÁµÄÄÚÈݶÌÓÚµ±Ç°ÅÌ¿éÖÐδ¶ÁµÄÄÚÈÝ->¾ÍÊ£×îºóÒ»¸öÅÌ¿éû¶ÁÁË 675 | if( VHD_BLOCK_SIZE - offset > len){ 676 | 677 | memcpy(textPtr,fileBuf + offset,len); 678 | textPtr += len; 679 | offset += len; 680 | oftPtr->fdt.filePtr += len; 681 | len = 0; 682 | } 683 | else{ 684 | // ºóÃæ»¹ÓÐÅÌ¿éδ¶Á£¬Ò²¾ÍÊÇ˵µ±Ç°ÅÌ¿éÊ£Óàδ¶ÁµÄ¶¼ÊÇÐèÒª¶ÁÈ¡µÄ 685 | memcpy(textPtr,fileBuf + offset,VHD_BLOCK_SIZE - offset); 686 | textPtr += (VHD_BLOCK_SIZE - offset); 687 | offset = 0; 688 | len -= (VHD_BLOCK_SIZE - offset); 689 | 690 | // ¸üÐÂÏÂÒ»¸öÅÌ¿éµÄÐÅÏ¢ 691 | blockNo = fatPtr->id; 692 | if(blockNo == VHD_BLOCK_FILE_END){ 693 | cout << "Error: do_read too long "<< endl; 694 | break; 695 | } 696 | fatPtr = getFatPtrByBlockNo(VhdPtr,blockNo); 697 | blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 698 | 699 | // ¼ÓÔØÏÂÒ»¸öÅÌ¿éµÄÄÚÈݵ½Buffer 700 | memcpy(fileBuf,blockPtr,VHD_BLOCK_SIZE); 701 | } 702 | 703 | } 704 | 705 | free(fileBuf); 706 | 707 | return lenToRead - len; 708 | } 709 | 710 | 711 | 712 | 713 | int do_write(OFT * oftPtr,char *text,int len,char wstyle){ 714 | 715 | int blockNo = oftPtr->fcb.blockNo; 716 | 717 | FAT *fatPtr = (FAT *)getBlockPtrByBlockNo(VhdPtr,blockNo); 718 | FAT *fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 719 | 720 | // PreProcess : According to Write Style 721 | writePreProcess(oftPtr,wstyle); 722 | int offset = oftPtr->fdt.filePtr; 723 | 724 | // PART1 : find the block system want to write 725 | while(offset >= VHD_BLOCK_SIZE){ 726 | // offset >= VHD_BLOCK_SIZE ->Turn to Next Block 727 | blockNo = fatPtr->id; 728 | 729 | if(blockNo == VHD_BLOCK_FILE_END){ 730 | // if not exist -> create one 731 | blockNo = getNextVhdBlock(fat1); 732 | // no available block exist 733 | if(blockNo == VHD_BLOCK_FILE_END){ 734 | cout << "Error: Not Enough Block "<< endl; 735 | return -1; 736 | } 737 | else{ 738 | // update (FAT1) 739 | // synchronize FAT2 740 | fatPtr->id = blockNo; 741 | fatPtr = (FAT *)getBlockPtrByBlockNo(VhdPtr,blockNo); 742 | fatPtr->id = VHD_BLOCK_FILE_END; 743 | } 744 | } 745 | 746 | fatPtr = (FAT *)getBlockPtrByBlockNo(VhdPtr,blockNo); 747 | offset -= VHD_BLOCK_SIZE; 748 | } 749 | 750 | // PART 2 751 | int lenTmp = 0; 752 | char *textPtr = text; 753 | unsigned char * buffer = getBlockBuffer(); 754 | unsigned char * blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 755 | 756 | 757 | while(len > lenTmp){ 758 | // load buffer,one block per time 759 | memcpy(buffer,blockPtr,VHD_BLOCK_SIZE); 760 | 761 | while (len >lenTmp && offset < VHD_BLOCK_SIZE){ 762 | *(buffer + offset) = *(textPtr); 763 | 764 | offset++; 765 | lenTmp++; 766 | textPtr++; 767 | } 768 | 769 | 770 | // load buffer to block 771 | memcpy(blockPtr,buffer,VHD_BLOCK_SIZE); 772 | 773 | // if this block is full and there text not be stored 774 | if(offset == VHD_BLOCK_SIZE && len > lenTmp){ 775 | // turn to next block and set offset = 0 776 | offset = 0; 777 | blockNo = fatPtr->id; 778 | // if block not exist ,then apply new one 779 | if(blockNo == VHD_BLOCK_FILE_END){ 780 | 781 | blockNo = getNextVhdBlock(fat1); 782 | if(blockNo == VHD_BLOCK_FILE_END){ 783 | cout << "Error: No available block " << endl; 784 | return EXIT_FAILURE; 785 | } 786 | 787 | blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 788 | fatPtr->id = blockNo; 789 | fatPtr = getFatPtrByBlockNo(VhdPtr,blockNo); 790 | fatPtr->id = VHD_BLOCK_FILE_END; 791 | 792 | } 793 | else{ 794 | blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 795 | fatPtr = getFatPtrByBlockNo(VhdPtr,blockNo); 796 | } 797 | } 798 | } 799 | 800 | 801 | // if file's read/write pointer > fcb's length -> update fcb's length 802 | oftPtr->fdt.filePtr += len; 803 | if((int)oftPtr->fcb.length < (int)oftPtr->fdt.filePtr){ 804 | oftPtr->fcb.length = oftPtr->fdt.filePtr; 805 | } 806 | 807 | free(buffer); 808 | // Release After Update file 809 | releaseBlock(blockNo); 810 | // Synchronize FAT2 811 | initFAT2(VhdPtr); 812 | 813 | return len; 814 | } 815 | 816 | 817 | /** 818 | * do_write ֮ǰ¸ù¾Ýwrite style ½øÐÐÔ¤´¦Àí 819 | * @param oftPtr [description] 820 | * @param wstyle [description] 821 | */ 822 | void writePreProcess(OFT* oftPtr,char wstyle){ 823 | 824 | /** 825 | * WS_REWRITE 0 826 | * WS_OVERWRITE 1 827 | * WS_APPEND 2 828 | */ 829 | switch(wstyle){ 830 | /* 831 | * REWRITE: Write the file from the begining of the FCB 832 | */ 833 | case WS_REWRITE: 834 | oftPtr->fdt.filePtr = 0; 835 | oftPtr->fcb.length = 0; 836 | break; 837 | /* 838 | * Overwrite ? is that necessary 839 | */ 840 | case WS_OVERWRITE: 841 | /* delete the end of the file's \0 */ 842 | if(oftPtr->fcb.metadata == MD_DATA_FILE && oftPtr->fcb.length != 0){ 843 | // ?TODO not right 844 | oftPtr->fdt.filePtr -= 1; 845 | } 846 | break; 847 | 848 | /* 849 | * Append : appending data to the File 850 | */ 851 | case WS_APPEND: 852 | 853 | if(oftPtr->fcb.metadata == MD_DIR_FILE){ 854 | oftPtr->fdt.filePtr = oftPtr->fcb.length; 855 | } 856 | else if(oftPtr->fcb.metadata == MD_DATA_FILE && oftPtr->fcb.length != 0){ 857 | /* delete the end of the file's \0 */ 858 | oftPtr->fdt.filePtr = oftPtr->fcb.length - 1; 859 | } 860 | break; 861 | } 862 | } 863 | 864 | 865 | 866 | unsigned char * getBlockBuffer(){ 867 | unsigned char *buffer = (unsigned char *)malloc(VHD_BLOCK_SIZE*sizeof(unsigned char)); 868 | if(buffer == NULL){ 869 | cout << "FAILURE: malloc for buffer" << endl; 870 | exit(EXIT_FAILURE); 871 | } 872 | 873 | return buffer; 874 | } 875 | 876 | 877 | void releaseBlock(int blockNo){ 878 | cout << "todo: release block .." << endl; 879 | FAT * fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 880 | 881 | int i; 882 | int next; 883 | 884 | cout << "todo : release blcok while" << endl; 885 | 886 | while(fat1[i].id != VHD_BLOCK_FILE_END && fat1[i].id != VHD_BLOCK_FREE){ 887 | 888 | next = fat1[i].id; 889 | fat1[i].id = VHD_BLOCK_FREE; 890 | i = next; 891 | 892 | } 893 | 894 | cout << "todo : end of file" << endl; 895 | fat1[blockNo].id = VHD_BLOCK_FILE_END; 896 | } 897 | 898 | 899 | 900 | int initOftByFileName(OFT *OftList,int piOft,char * filename,unsigned char metadata){ 901 | 902 | 903 | char *fname = strtok(filename,"."); 904 | char *ename = strtok(NULL,"."); 905 | OFT * pOftPtr = OftList + piOft; 906 | 907 | cout << "File Name "<fcb.length,buffer); 913 | 914 | // Find FCB Index In Directory File 915 | int indexOfFcb = getIndexOfFcb(pOftPtr,fname,ename,metadata); 916 | if(indexOfFcb == OBJECT_NOT_FOUND){ 917 | cout << "No Such File Exist " << endl; 918 | return FAILURE; 919 | } 920 | FCB * fcbPtr = (FCB *)buffer + indexOfFcb; 921 | 922 | // Apply for new OFT 923 | int indexOfOft = getNextOft(OftList); 924 | if(indexOfOft == OBJECT_NOT_FOUND){ 925 | cout << "User Open File is Full" << endl; 926 | return FAILURE; 927 | } 928 | OFT * cOftPtr = OftList + indexOfOft; 929 | 930 | 931 | initOft(cOftPtr); 932 | loadFcb2Oft(cOftPtr,fcbPtr); 933 | 934 | 935 | if(pOftPtr != NULL){ 936 | cOftPtr->fdt.fdEntryNo = indexOfFcb; 937 | cOftPtr->fdt.pdfBlockNo = pOftPtr->fcb.blockNo; 938 | if(fcbPtr->metadata == MD_DATA_FILE){ 939 | strcpy(cOftPtr->fdt.dirName,(string(pOftPtr->fdt.dirName) + string(filename)).c_str()); 940 | } 941 | else if(fcbPtr->metadata == MD_DIR_FILE){ 942 | strcpy(cOftPtr->fdt.dirName,(string(pOftPtr->fdt.dirName) + string(filename) + string("\\")).c_str()); 943 | } 944 | } 945 | 946 | return indexOfOft; 947 | } 948 | 949 | 950 | 951 | int getIndexOfFcb(OFT *oftPtr,char * fname,char *ename,unsigned char metadata){ 952 | 953 | int i; 954 | //int fcbNum = int(oftPtr->fcb.length/sizeof(FCB)); 955 | int fcbNum = int(VHD_BLOCK_SIZE/sizeof(FCB)); 956 | char buffer[FILE_BUF_SIZE]; 957 | 958 | oftPtr->fdt.filePtr = 0; 959 | // cout <<"before read : "<fcb.length,buffer); 961 | do_read(oftPtr,VHD_BLOCK_SIZE,buffer); 962 | 963 | //cout <<"after read: "<metadata == metadata && 970 | strcmp(fcbPtr->fileName,fname)==0 && 971 | strcmp(fcbPtr->fileNameExten,ename)==0){ 972 | 973 | return i; 974 | } 975 | } 976 | 977 | return OBJECT_NOT_FOUND; 978 | } 979 | 980 | 981 | 982 | /** 983 | * ´Ó´æ´¢Îļþ[txt]ÖжÁÈ¡ÐÅÏ¢µ½Buffer 984 | */ 985 | void readVhdFile(unsigned char * VhdPtr){ 986 | FILE * sysFile; 987 | 988 | VhdPtr = (unsigned char *)malloc 989 | sysFile = fopen(FileSysName,"r"); 990 | if(sysFile != NULL){ 991 | // Write VhdBuffer from sysFile 992 | fread(VhdBuffer,VHD_SIZE,1,sysFile); 993 | fclose(sysFile); 994 | // FileSysMagicNum: "10101010" 995 | if(memcmp(VhdBuffer,FileSysMagicNum,MAGIC_NUM_LEN) == 0){ 996 | // VHD <- VhdBuffer 997 | memcpy(VhdPtr,VhdBuffer,VHD_SIZE); 998 | cout << "Success: FileSys.txt Read" < 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | using namespace std; 14 | 15 | 16 | /** 17 | * CONST DEFINE | 定义常量 18 | * 19 | * @Author Scorpion 20 | * 21 | */ 22 | 23 | 24 | /** 25 | * COMMON | 公用 26 | * 27 | * FALSE  :假 28 | * TRUE :真 29 | * OBJECT_NOT_FOUND : 对象没有找到 30 | */ 31 | #define FALSE 0 32 | #define TRUE 1 33 | #define SUCCESS 1 34 | #define FAILURE -1 35 | #define OBJECT_NOT_FOUND -1 36 | 37 | 38 | /** 39 | * VHD: Virtual Hard Disk 虚拟磁盘 40 | * 41 | * VHD_SIZE :虚拟磁盘的大小 42 | * VHD_BLOCK_SIZE : VHD中单个盘块的大小 43 | * VHD_BLOCK_FREE :FAT表中盘块空闲的标志 44 | * VHD_BLOCK_FILE_END :FAT 文件结束标志 45 | * VHD_BLOCK_NUM : 盘块的总数 46 | * 47 | */ 48 | #define VHD_SIZE 1024000 49 | #define VHD_BLOCK_SIZE 1024 50 | #define VHD_BLOCK_FREE 0 51 | #define VHD_BLOCK_FILE_END 65535 52 | #define VHD_BLOCK_NUM 1000 53 | 54 | /** 55 | * File System Structure | 文件系统结构 56 | * 57 | * BLOCK_INDEX_BOOT_BLOCK :引导块的首盘块号 58 | * BLOCK_INDEX_FAT1 : FAT1 的首盘块号 59 | * BLOCK_INDEX_FAT2 : FAT2 的首盘块号 60 | * BOLCK_INDEX_ROOT_DIR : 根目录文件的盘块号 61 | * 62 | */ 63 | 64 | /** 65 | * FAT File System Structure 66 | * FAT 文件系统结构 67 | * 68 | * |Start| End | Name | Note | 69 | * |-----|-----|------------|-------------------| 70 | * | 0 | 0 | Boot Block | 引导区 | 71 | * |-----|-----|------------|-------------------| 72 | * | 1 | 2 | FAT1 | 文件分配表 | 73 | * |-----|-----|------------|-------------------| 74 | * | 3 | 4 | FAT2 | 文件分配表-备份 | 75 | * |-----|-----|------------|-------------------| 76 | * | 5 | 5 | ROOT DIR | 根目录区 | 77 | * |-----|-----|------------|-------------------| 78 | * | 5 | 1000| DATA Area | 数据区 | 79 | * 80 | */ 81 | 82 | #define BLOCK_INDEX_BOOT_BLOCK 0 83 | #define BLOCK_INDEX_FAT1 1 84 | #define BLOCK_INDEX_FAT2 3 85 | #define BLOCK_INDEX_ROOT_DIR 5 86 | #define BLOCK_INDEX_DATA_AREA 5 87 | 88 | #define BLOCK_NUM_BOOT_BLOCK 1 89 | #define BLOCK_NUM_FAT 2 90 | #define BLOCK_NUM_ROOT_DIR 1 91 | 92 | 93 | /** 94 | * File Sytem + Boot Block | 文件系统 95 | */ 96 | 97 | #define MAGIC_NUM_LEN 8 98 | #define SYS_INFO_LEN 200 99 | static const char * FileSysMagicNum = "10101010"; 100 | 101 | 102 | /** 103 | * File Buffer :文件缓冲 104 | */ 105 | #define FILE_BUF_SIZE 10000 106 | 107 | 108 | /** 109 | * FCB 110 | * FILE_NAME_LEN : 文件名的长度 [Filename Extension Length] 111 | * FILE_NAME_EXTEN_LEN : 文件拓展名的长度[Filename Extension Length] 112 | * [metadata] 113 | * MD_DIR_FILE :目录文件 114 | * MD_DATA_FILE :用户数据文件 115 | */ 116 | #define FILE_NAME_LEN 8 117 | #define FILE_NAME_EXTEN_LEN 3 118 | #define MD_DIR_FILE 0 119 | #define MD_DATA_FILE 1 120 | 121 | 122 | 123 | //#define FILE_META_LEN 100 124 | 125 | 126 | /** 127 | * File Discriptor Table | 文件描述符表 128 | * 129 | * DIR_NAME_LEN : 文件目录名的长度 130 | */ 131 | #define DIR_NAME_LEN 80 132 | 133 | 134 | 135 | /** 136 | * Open File Table |用户打开文件表 137 | * 138 | * OFT_NUM : OftList的长度 139 | */ 140 | #define OFT_NUM 10 141 | 142 | 143 | 144 | /** 145 | * Data Store File | 数据存储文件TXT 146 | * 147 | * MAGIC_NUM_LEN :魔数的长度 [Magic Number Length] 148 | * FileSysMagicNum : 文件系统DATA储存文件的文件魔数 149 | * FileSysName :文件系统DATA储存文件的名称 150 | * 151 | */ 152 | static const char * FileSysName = "FileSys.txt"; 153 | 154 | 155 | /** 156 | * File Read Style | 文件写入的几种方式 157 | * 158 | * WS_REWRITE : 159 | * WS_OVERWRITE : 160 | * WS_APPEND : 追加写 161 | */ 162 | #define WS_REWRITE 0 163 | #define WS_OVERWRITE 1 164 | #define WS_APPEND 2 165 | 166 | 167 | /** 168 | * Console Command | 终端命令 169 | * CMD_NUM :命令的个数 170 | * CMD_LEN : 命令的长度 171 | * CmdGroup: 指令集 172 | */ 173 | #define CMD_NUM 15 174 | #define CMD_LEN 10 175 | static const char CmdGroup[CMD_NUM][CMD_LEN] = { 176 | "mkdir", "rmdir", "ls", "cd", "create", 177 | "rm", "open", "close", "write", 178 | "read", "exit", "help","bigfile" 179 | }; 180 | 181 | static const char sysInfo[SYS_INFO_LEN] = "System File System @Author Scorpion \n File System Type: FAT12 \n [Single User Multiple Layer Directory]"; 182 | 183 | 184 | 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.2/SysStructure.cpp: -------------------------------------------------------------------------------- 1 | #include "SysStructure.h" 2 | 3 | /** 4 | * IO Operation 5 | */ 6 | 7 | /* 保存整个虚拟磁盘文件 */ 8 | void saveVhdFile(unsigned char *VhdPtr,unsigned char *vhdBuf){ 9 | 10 | memcpy(VhdPtr,vhdBuf,VHD_SIZE); 11 | } 12 | 13 | /* 保存某个盘块 */ 14 | void saveVhdFile(unsigned char *VhdPtr,int blockNo,unsigned char *blockBuf){ 15 | 16 | unsigned char * blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 17 | memcpy(blockPtr,blockBuf,VHD_BLOCK_SIZE); 18 | } 19 | 20 | /* 保存某个盘块的对应偏移量offset的FCB*/ 21 | void saveVhdFile(unsigned char *VhdPtr,int blockNo,int offset,unsigned char *fcbBuf){ 22 | 23 | unsigned char * blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 24 | unsigned char * fcbPtr = blockPtr + offset * sizeof(FCB); 25 | 26 | memcpy(fcbPtr,fcbBuf,sizeof(FCB)); 27 | } 28 | 29 | /* 读取整个虚拟磁盘文件到Vhd Buffer*/ 30 | void readVhdFile(unsigned char *VhdPtr,unsigned char *vhdBuf){ 31 | 32 | memcpy(vhdBuf,VhdPtr,VHD_SIZE); 33 | } 34 | 35 | /* 读取整个盘块到对应的Block Buffer */ 36 | void readVhdFile(unsigned char *VhdPtr,int blockNo,unsigned char *blockBuf){ 37 | 38 | unsigned char * blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 39 | 40 | memcpy(blockBuf,blockPtr,VHD_BLOCK_SIZE); 41 | } 42 | 43 | /* 读取FCB到对应的fcbBuf*/ 44 | void readVhdFile(unsigned char *VhdPtr,int blockNo,int offset,unsigned char *fcbBuf){ 45 | unsigned char * blockPtr = getBlockPtrByBlockNo(VhdPtr,blockNo); 46 | unsigned char * fcbPtr = blockPtr + offset * sizeof(FCB); 47 | 48 | memcpy(fcbBuf,blockPtr,sizeof(FCB)); 49 | } 50 | 51 | 52 | 53 | /** 54 | * Boot Block 55 | */ 56 | /* 初始化引导块 */ 57 | void initBootBlock(unsigned char *VhdPtr){ 58 | 59 | BootBlock * bootBlock = (BootBlock *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_BOOT_BLOCK);; 60 | 61 | strcpy(bootBlock->magicNum,FileSysMagicNum); 62 | strcpy(bootBlock->sysInfo,sysInfo); 63 | bootBlock->dataBlockPtr = getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_DATA_AREA); 64 | bootBlock->rootBlockNo = BLOCK_INDEX_ROOT_DIR; 65 | } 66 | 67 | 68 | 69 | /** 70 | * FAT 71 | * File Allocation Table 72 | */ 73 | 74 | /* 初始化FAT1 */ 75 | void initFat1(unsigned char *VhdPtr){ 76 | FAT * fat1 = getFat1Ptr(VhdPtr); 77 | 78 | int i; 79 | 80 | /** 81 | * 下列盘块对应的FAT表中的值设置为 文件结束标志 82 | * |Start| End | Name | Note | 83 | * |-----|-----|------------|-------------------| 84 | * | 0 | 0 | Boot Block | 引导区 | 85 | * |-----|-----|------------|-------------------| 86 | * | 1 | 2 | FAT1 | 文件分配表 | 87 | * |-----|-----|------------|-------------------| 88 | * | 3 | 4 | FAT2 | 文件分配表-备份 | 89 | * |-----|-----|------------|-------------------| 90 | */ 91 | for(i = BLOCK_INDEX_BOOT_BLOCK;i < BLOCK_INDEX_DATA_AREA; i++){ 92 | fat1[i].id = VHD_BLOCK_FILE_END; 93 | } 94 | 95 | /** 96 | * 下列数据区的盘块对应的FAT表中的值设置为 FREE 97 | * |-----|-----|------------|-------------------| 98 | * | 5 | 1000| DATA Area | 数据区 | 99 | * |-----|-----|------------|-------------------| 100 | */ 101 | for(i = BLOCK_INDEX_DATA_AREA;i < VHD_BLOCK_NUM; i++){ 102 | 103 | fat1[i].id = VHD_BLOCK_FREE; 104 | } 105 | 106 | /** 107 | * 将ROOT_DIR 的表项设为END 108 | * |-----|-----|------------|-------------------| 109 | * | 5 | 5 | ROOT_DIR | 根目录 | 110 | * |-----|-----|------------|-------------------| 111 | */ 112 | fat1[BLOCK_INDEX_ROOT_DIR].id = VHD_BLOCK_FILE_END; 113 | } 114 | 115 | /* 同步FAT2 */ 116 | void updateFat2(unsigned char *VhdPtr){ 117 | 118 | FAT * fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 119 | FAT * fat2 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT2); 120 | 121 | memcpy(fat1,fat2,BLOCK_NUM_FAT * VHD_BLOCK_SIZE); 122 | } 123 | 124 | 125 | /* 获取FAT1的FAT指针*/ 126 | FAT * getFat1Ptr(unsigned char *VhdPtr){ 127 | FAT * fat1 = (FAT *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_FAT1); 128 | return fat1; 129 | } 130 | 131 | /* 根据盘块号获取盘块号对应的FAT的指针 */ 132 | FAT * getFatPtr(unsigned char *VhdPtr,int blockNo){ 133 | FAT * fat1 = getFat1Ptr(VhdPtr); 134 | return fat1 + blockNo; 135 | } 136 | 137 | /* 根据盘块号和偏移量获取FCB的指针 : ? offset > fcbNum*/ 138 | FCB * getFcbPtr(unsigned char *VhdPtr,int blockNo,int offset){ 139 | 140 | FCB * fcbPtr = (FCB *)(getBlockPtrByBlockNo(VhdPtr,blockNo) + offset * sizeof(FCB)); 141 | return fcbPtr; 142 | } 143 | 144 | 145 | /* 获取下一个空闲的盘块 并更新FAT表 */ 146 | int getNextBlock(unsigned char *VhdPtr,int blockNo){ 147 | 148 | FAT * fat1 = getFat1Ptr(VhdPtr); 149 | FAT * fatPtr = fat1; 150 | int fatNum = (BLOCK_NUM_FAT * VHD_BLOCK_SIZE )/(sizeof(FAT)); 151 | 152 | for(int i = 0; iid == VHD_BLOCK_FREE){ 154 | return i; 155 | } 156 | } 157 | return OBJECT_NOT_FOUND; 158 | } 159 | 160 | /* 释放占据的盘块*/ 161 | void freeBlock(unsigned char *VhdPtr,int blockNo){ 162 | 163 | FAT * fat1 = getFat1Ptr(VhdPtr); 164 | FAT * fatPtr = fat1 + blockNo; 165 | 166 | while(fatPtr->id != VHD_BLOCK_FILE_END){ 167 | fatPtr->id = VHD_BLOCK_FREE; 168 | fatPtr++; 169 | } 170 | 171 | fatPtr->id = VHD_BLOCK_FREE; 172 | 173 | } 174 | 175 | 176 | /** 177 | * Root Block 178 | */ 179 | 180 | /* 初始化根目录的磁盘块 */ 181 | void initRootBlock(unsigned char *VhdPtr){ 182 | 183 | initDirectoryBlock(VhdPtr,BLOCK_INDEX_ROOT_DIR,BLOCK_INDEX_ROOT_DIR); 184 | } 185 | 186 | 187 | /** 188 | * FCB 189 | * File Control Block 190 | */ 191 | 192 | /* 初始化FCB的时间和日期 */ 193 | void setFcbDateTime(FCB *fcbPtr){ 194 | time_t rawTime = time(NULL); 195 | struct tm *time = localtime(&rawTime); 196 | /*root->time 是unsigned short int类型的数据, 32位编译器下长16位,64位编译器下长32位 197 | * 这里考虑32位编译器, 所以完整的表示一个时间的秒数是不够长的,所以,保存秒数的一半 198 | * 这样小时占5位,分钟占6位,秒占5位 199 | */ 200 | unsigned short currentTime = time->tm_hour * 2048 + time->tm_min*32 + time->tm_sec/2; 201 | 202 | /** 203 | * 年份我们保存的是实际值-2000, time->tm_mon要+1是因为,这个结构设计的时候0代表1月 204 | * 同理,年份占7位,月份占4位,日期占5位 TODO -100 205 | */ 206 | unsigned short currentDate = (time->tm_year-100)*512 + (time->tm_mon+1)*32 + (time->tm_mday); 207 | 208 | fcbPtr->createDate = currentDate; 209 | fcbPtr->createTime = currentTime; 210 | } 211 | 212 | /* 初始化空闲的FCB */ 213 | void initFcb(FCB *fcbPtr){ 214 | memset(fcbPtr,0,sizeof(FCB)); 215 | 216 | fcbPtr->length = 0; 217 | fcbPtr->isUse = FALSE; 218 | strcpy(fcbPtr->fileName,""); 219 | strcpy(fcbPtr->fileNameExten,""); 220 | } 221 | 222 | /* 根据文件名和类型初始化FCB */ 223 | void initFcb(FCB *fcbPtr,char *fname,char *ename,unsigned char metadata){ 224 | 225 | initFcb(fcbPtr); 226 | fcbPtr->metadata = metadata; 227 | strcmp(fcbPtr->fileName,fname); 228 | strcmp(fcbPtr->fileNameExten,ename); 229 | 230 | fcbPtr->isUse = TRUE; 231 | } 232 | 233 | void initDirectoryBlock(unsigned char *VhdPtr,int curBlockNo,int parentBlockNo){ 234 | 235 | FCB * fcbPtr = getFcbPtr(VhdPtr,curBlockNo,0); 236 | 237 | FCB * dotPtr = fcbPtr; 238 | FCB * dotDotPtr = fcbPtr + 1; 239 | 240 | initFcb(dotPtr,".","di",MD_DIR_FILE); 241 | dotPtr->blockNo = curBlockNo; 242 | dotPtr->length = 2 * sizeof(FCB); 243 | 244 | FCB * parentFcbPtr = getFcbPtr(VhdPtr,parentBlockNo,0); 245 | memcpy(dotDotPtr,parentFcbPtr,sizeof(FCB)); 246 | strcpy(dotDotPtr->fileName,".."); 247 | } 248 | 249 | /* 匹配文件名和文件类型是否匹配 */ 250 | int fileIsEqual(FCB * fcbPtr,char *fname,char *ename,unsigned char metadata){ 251 | 252 | if(strcmp(fcbPtr->fileName,fname) == 0 && strcmp(fcbPtr->fileNameExten,ename) == 0 && fcbPtr->metadata == metadata){ 253 | 254 | return TRUE; 255 | } 256 | 257 | return FALSE; 258 | } 259 | 260 | /* 在当前block中 申请下一个空闲的FCB | 当前的OFT 默认为目录文件 */ 261 | int getNextFcb(unsigned char * VhdPtr,int blockNo){ 262 | 263 | FCB * fcbPtr = getFcbPtr(VhdPtr,blockNo,0); 264 | 265 | int i; 266 | int fcbNum = VHD_BLOCK_SIZE / sizeof(FCB); 267 | 268 | for(i = 0; i < fcbNum; i++,fcbPtr++){ 269 | if(fcbPtr->isUse == FALSE){ 270 | return i; 271 | } 272 | } 273 | 274 | return OBJECT_NOT_FOUND; 275 | } 276 | 277 | /* 打印文件信息 | 根据文件类型选择不同的打印方式 */ 278 | void printFcbInfo(FCB *fcbPtr){ 279 | 280 | unsigned int length = fcbPtr->length; 281 | 282 | if(length == 0){ 283 | return; 284 | } 285 | 286 | if(fcbPtr->metadata == MD_DATA_FILE){ 287 | 288 | 289 | printf("%s.%s\t%dB\t%d/%d/%d\t%02d:%02d:%02d\n", 290 | fcbPtr->fileName, 291 | fcbPtr->fileNameExten, 292 | length, 293 | (fcbPtr->createDate>>9)+2000, 294 | (fcbPtr->createDate>>5)&0x000f, 295 | (fcbPtr->createDate)&0x001f, 296 | (fcbPtr->createTime>>11), 297 | (fcbPtr->createTime>>5)&0x003f, 298 | (fcbPtr->createTime)&0x001f * 2); 299 | 300 | 301 | } 302 | else if(fcbPtr->metadata == MD_DIR_FILE){ 303 | 304 | printf("%s\\\t\t%d/%d/%d\t%d:%d:%d\n", 305 | fcbPtr->fileName, 306 | (fcbPtr->createDate>>9)+2000, 307 | (fcbPtr->createDate>>5)&0x000f, 308 | (fcbPtr->createDate)&0x001f, 309 | (fcbPtr->createTime>>11), 310 | (fcbPtr->createTime>>5)&0x003f, 311 | (fcbPtr->createTime)&0x001f * 2); 312 | } 313 | } 314 | 315 | 316 | 317 | /** 318 | * FDT 319 | * Fild Descriptor Table 320 | */ 321 | 322 | void initFdt(FDT *fdtPtr){ 323 | fdtPtr->isUpate = FALSE; 324 | fdtPtr->filePtr = 0; 325 | } 326 | 327 | 328 | 329 | /** 330 | * OFT 331 | * Open File Table 332 | */ 333 | 334 | 335 | 336 | void initOft(OFT *oftPtr){ 337 | 338 | initFcb(&(oftPtr->fcb)); 339 | initFdt(&(oftPtr->fdt)); 340 | 341 | oftPtr->isUse = FALSE; 342 | } 343 | 344 | 345 | void initOft(OFT * OftList,int curOftIndex,int parOftIndex,int fdEntryNo,FCB *fcbPtr){ 346 | 347 | OFT * curOftPtr = OftList + curOftIndex; 348 | OFT * parOftPtr = OftList + parOftIndex; 349 | 350 | initOft(curOftPtr); 351 | 352 | cloneFcb2Oft(curOftPtr,fcbPtr); 353 | 354 | if(fcbPtr->metadata == MD_DATA_FILE){ 355 | strcpy(curOftPtr->fdt.dirName,(string(parOftPtr->fdt.dirName)+string(curOftPtr->fcb.fileName)).c_str()); 356 | } 357 | else if(fcbPtr->metadata == MD_DIR_FILE){ 358 | strcpy(curOftPtr->fdt.dirName,(string(parOftPtr->fdt.dirName)+string(curOftPtr->fcb.fileName)+string("\\")).c_str()); 359 | } 360 | 361 | curOftPtr->fdt.fdEntryNo = fdEntryNo; 362 | curOftPtr->fdt.filePtr = 0; 363 | curOftPtr->fdt.isUpate = FALSE; 364 | curOftPtr->fdt.pdfBlockNo = parOftPtr->fcb.blockNo; 365 | 366 | curOftPtr->isUse = TRUE; 367 | } 368 | 369 | 370 | /* 初始化根目录文件的打开文件 */ 371 | void initRootOft(unsigned char* VhdPtr,OFT *OftList){ 372 | 373 | OFT *oftPtr = OftList; 374 | 375 | FCB *fcbPtr = getFcbPtr(VhdPtr,BLOCK_INDEX_ROOT_DIR,0); 376 | 377 | initOft(OftList,0,0,0,fcbPtr); 378 | 379 | strcpy(oftPtr->fdt.dirName,"\\root\\"); 380 | 381 | } 382 | 383 | 384 | 385 | 386 | 387 | 388 | /* 获取父打开文件在OftList的Index*/ 389 | int getParentOft(OFT *OftList,int curOft){ 390 | 391 | int i; 392 | 393 | for( i=0; i < OFT_NUM; i++){ 394 | if(OftList[i].isUse == FALSE){ 395 | continue; 396 | } 397 | 398 | if(OftList[curOft].fdt.pdfBlockNo == OftList[i].fcb.blockNo){ 399 | return i; 400 | } 401 | } 402 | return OBJECT_NOT_FOUND; 403 | } 404 | 405 | 406 | /* 将OFT中的信息拷贝到FCB中*/ 407 | void cloneFcb2Oft(OFT *oftPtr,FCB *fcbPtr){ 408 | memcpy(&(oftPtr->fcb),fcbPtr,sizeof(FCB)); 409 | } 410 | 411 | /* 将Oft中的FCB信息保存到FCB中*/ 412 | void cloneOft2Fcb(OFT *oftPtr,FCB *fcbPtr){ 413 | memcpy(fcbPtr,&(oftPtr->fcb),sizeof(FCB)); 414 | } 415 | 416 | 417 | unsigned char * getBlockPtrByBlockNo(unsigned char *VHDPtr,int blockNo){ 418 | unsigned char * blockPtr = VHDPtr + blockNo * VHD_BLOCK_SIZE; 419 | return blockPtr; 420 | } 421 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.2/SysStructure.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYS_STRUCTURE_H_ 2 | #define _SYS_STRUCTURE_H_ 3 | 4 | #include "Common.h" 5 | 6 | 7 | 8 | /** 9 | * FAT File System Structure 10 | * FAT 文件系统结构 11 | * 12 | * |Start| End | Name | Note | 13 | * |-----|-----|------------|-------------------| 14 | * | 0 | 0 | Boot Block | 引导区 | 15 | * |-----|-----|------------|-------------------| 16 | * | 1 | 2 | FAT1 | 文件分配表 | 17 | * |-----|-----|------------|-------------------| 18 | * | 3 | 4 | FAT2 | 文件分配表-备份 | 19 | * |-----|-----|------------|-------------------| 20 | * | 5 |1000 | DATA BLOCK| 数据区 | 21 | * |-----|-----|------------|-------------------| 22 | * | 5 | 5 | ROOT_DIR | 根目录文件 | 23 | * 24 | */ 25 | 26 | /** 27 | * Boot Block | 引导块 28 | * 29 | * @note 30 | * 引导块占用第0号物理块,不属于文件系统管辖, 31 | * 如果系统中有多个文件系统,只有根文件系统才 32 | * 有引导程序放在引导块中,其余文件系统都不 33 | * 使用引导块 34 | * 35 | */ 36 | typedef struct BootBlock 37 | { 38 | /** 39 | * Magic Number | 魔数 40 | * 41 | * @value 42 | * 10101010 43 | */ 44 | char magicNum[MAGIC_NUM_LEN]; 45 | 46 | /** 47 | * System Information | 系统信息 48 | */ 49 | char sysInfo[SYS_INFO_LEN]; 50 | 51 | /** 52 | * Root Directory Block Number |根目录文件的盘块号 53 | */ 54 | unsigned short rootBlockNo; 55 | 56 | /** 57 | * Data Area VHD Block Pointer | 指向数据区首盘块的指针 58 | * 59 | */ 60 | unsigned char *dataBlockPtr; 61 | 62 | }BootBlock; 63 | 64 | /** 65 | * FAT : File Allocation Table 66 | */ 67 | typedef struct FAT 68 | { 69 | unsigned short id; 70 | } FAT; 71 | 72 | /** 73 | * @name 74 | * File Control Block | 文件控制块 75 | * @note 76 | * 用户存储文件的描述和控制信息的数据结构 77 | * 常用的有FCB和iNode,在FAT文件系统中使用的是FCB 78 | * 文件与文件控制块一一对应关系。 79 | *------------------------------------------------- 80 | * @name 81 | * File Directoty | 目录文件 82 | * @note 83 | * 文件控制块的有序集合,可以理解成好多个FCB的数组 84 | * 85 | * 86 | * ------------------------------------------------- 87 | * @name 88 | * File Directoty Entry| 文件的目录项 89 | * @note 90 | * 一个FCB就是一个文件目录项 91 | * 文件目录项分类: 92 | * 1. 卷标目录项 93 | * 2. "." 目录项 94 | * 3. ".."目录项 95 | * 4. 短文件名目录项* 96 | * 5. 尝文件名目录项 97 | * 98 | * 短文件名目录项是最重要的数据结构,其中存放着有关 99 | * 子目录或文件的短文件名、属性、起始簇号、时间值 100 | * 以及内容大小等信息。 101 | * @link 102 | * http://blog.csdn.net/eastonwoo/article/details/8450060 103 | * ------------------------------------------------- 104 | */ 105 | typedef struct FCB 106 | { 107 | /** 108 | * File Name | 文件名称 109 | * @length 8B 110 | */ 111 | char fileName[FILE_NAME_LEN]; //file name 112 | 113 | /** 114 | * Filename Extension | 文件拓展名 115 | * @length 3B 116 | */ 117 | char fileNameExten[FILE_NAME_EXTEN_LEN]; // 118 | 119 | /** 120 | * Metadata | 元数据 121 | * @note 元数据[metadata] 等同于 文件属性[attribute] 122 | * 每一位代表文件是具备该属性(具备:1 不具备:0) 123 | * 目前实现的文件系统里面只用到了其中一位用于表示是数据文件还是目录文件 124 | * @length 1B 125 | * @value 126 | * MD_DATA_FILE : 数据文件 127 | * MD_DIR_FILE : 目录文件 128 | * 129 | */ 130 | unsigned char metadata; 131 | 132 | /** 133 | * Create Time | 文件创建时间 134 | * 135 | * @note 136 | * root->time 是unsigned short int类型的数据, 32位编译器下长16位,64位编译器下长32位 137 | * 这里考虑32位编译器, 所以完整的表示一个时间的秒数是不够长的,所以,保存秒数的一半 138 | * 这样小时占5位,分钟占6位,秒占5位 139 | * @value 140 | * @length 141 | * 142 | */ 143 | unsigned short createTime; 144 | 145 | /** 146 | * Create Date | 创建日期 147 | * @note 148 | * 年份我们保存的是实际值-2000, time->tm_mon要+1是因为,这个结构设计的时候0代表1月 149 | * 同理,年份占7位,月份占4位,日期占5位 150 | * @value 151 | * 152 | */ 153 | unsigned short createDate; 154 | 155 | /** 156 | * Block Number | 盘块号 157 | * @note FCB的首盘块号 158 | * @length 2B 159 | */ 160 | unsigned short blockNo; //this file's the first Block Number 161 | 162 | 163 | /** 164 | * File Length | 文件大小/长度 165 | * @length 4B 166 | */ 167 | unsigned long length; 168 | 169 | 170 | /** 171 | * Is Free | 是否被占用 172 | * @value 173 | * TRUE : 正在被使用 174 | * FALSE : FCB空闲 175 | * @length 1B 176 | */ 177 | char isUse; 178 | }FCB; 179 | 180 | 181 | /** 182 | * File Discriptor Table | 文件描述符表 183 | * @note 184 | * 185 | * @wiki 186 | * 文件描述符、文件描述符表、打开文件表、目录项、索引节点之间的联系 187 | * http://www.cnblogs.com/yanenquan/p/4614805.html 188 | * 189 | */ 190 | typedef struct FDT{ 191 | 192 | /** 193 | * File Pointer | 文件读写指针 / 游标 194 | * @note 195 | * 用于记录读取的位置 196 | */ 197 | int filePtr; 198 | 199 | /** 200 | * Is Update | 是否更新 201 | * @note 202 | * FCB是否更新过 203 | * @value 204 | * TRUE : 跟新过 205 | * FALSE : 未更新 206 | */ 207 | char isUpate; //to Record the Change of FCB-> Change:TRUE 208 | 209 | /** 210 | * Parent Directory File's Block Number 211 | * @note 212 | * 当前文件的父目录文件所在的盘块号 213 | * 214 | */ 215 | int pdfBlockNo; 216 | 217 | /** 218 | * 219 | * File Directory Entry Number 220 | * @note 221 | * 当前文件的父目录文件中的目录项的序号 222 | * 即该文件在父目录文件中对应的FCB序号 223 | * @name 224 | * File Directory Entry 目录项 225 | * 参见FCB.h中的介绍 226 | */ 227 | int fdEntryNo; // Parent Dirrectory Entry Number in parentDirBlockNo 228 | 229 | /** 230 | * Directory Name | 路径名称 231 | * @demo 232 | * \root\scropion\ 233 | * @length 234 | * 80 235 | */ 236 | char dirName[DIR_NAME_LEN]; 237 | }FDT; 238 | 239 | /* 240 | * Open File Table | 打开文件表 241 | * @note 242 | * 打开文件表包含两部分 : 用户文件描述表 和 内存FCB表 243 | * 244 | */ 245 | typedef struct OFT 246 | { 247 | /** 248 | * File Control Block | 文件控制块 249 | */ 250 | FCB fcb; 251 | 252 | /** 253 | * File Discriptor Table | 文件描述符表 254 | */ 255 | FDT fdt; 256 | 257 | /* 258 | * Is Use |是否被占用 259 | * @note 260 | * 当前OFT是否被占用 261 | * @value 262 | * TRUE : 正在被使用 263 | * FALSE : OFT空闲 264 | */ 265 | char isUse; 266 | }OFT; 267 | 268 | 269 | 270 | /** 271 | * IO Operation 272 | */ 273 | 274 | /* 保存整个虚拟磁盘文件 */ 275 | /* Save Hard Disk File */ 276 | //void saveHdFile(unsigned char *VhdPtr); 277 | 278 | /* Read Hard Disk File*/ 279 | //void readHdFile(unsigned char *VhdPtr); 280 | /* 保存整个虚拟磁盘文件 */ 281 | void saveVhdFile(unsigned char *VhdPtr,unsigned char *vhdBuf); 282 | 283 | /* 保存某个盘块 */ 284 | void saveVhdFile(unsigned char *VhdPtr,int blockNo,unsigned char *blockBuf); 285 | 286 | /* 保存某个盘块的对应偏移量offset的FCB*/ 287 | void saveVhdFile(unsigned char *VhdPtr,int blockNo,int offset,unsigned char *fcbBuf); 288 | 289 | /* 读取整个虚拟磁盘文件到Vhd Buffer*/ 290 | void readVhdFile(unsigned char *VhdPtr,unsigned char *vhdBuf); 291 | 292 | /* 读取整个盘块到对应的Block Buffer */ 293 | void readVhdFile(unsigned char *VhdPtr,int blockNo,unsigned char *blockBuf); 294 | 295 | /* 读取FCB到对应的fcbBuf*/ 296 | void readVhdFile(unsigned char *VhdPtr,int blockNo,int offset,unsigned char *fcbBuf); 297 | 298 | 299 | 300 | /** 301 | * Boot Block 302 | */ 303 | /* 初始化引导块 */ 304 | void initBootBlock(unsigned char *VhdPtr); 305 | 306 | 307 | /** 308 | * Root Block 309 | */ 310 | 311 | /* 初始化根目录的磁盘块 */ 312 | void initRootBlock(unsigned char *VhdPtr); 313 | 314 | 315 | /** 316 | * FAT 317 | * File Allocation Table 318 | */ 319 | 320 | /* 初始化FAT1 */ 321 | void initFat1(unsigned char *VhdPtr); 322 | 323 | /* 同步FAT2 */ 324 | void updateFat2(unsigned char *VhdPtr); 325 | 326 | 327 | /* 获取FAT1的FAT指针*/ 328 | FAT * getFat1Ptr(unsigned char *VhdPtr); 329 | 330 | /* 根据盘块号获取盘块号对应的FAT的指针 */ 331 | FAT * getFatPtr(unsigned char *VhdPtr,int blockNo); 332 | 333 | /* 根据盘块号和偏移量获取FCB的指针 : ? offset > fcbNum*/ 334 | FCB * getFcbPtr(unsigned char *VhdPtr,int blockNo,int offset); 335 | 336 | /* 根据盘块号和偏移量获取FCB的指针 : ? offset > fcbNum */ 337 | //FCB * getNextFcbPtr(unsigned char *VhdPtr,int blockNo,int offset); 338 | 339 | /* 获取下一个空闲的盘块 并更新FAT表 */ 340 | int getNextBlock(unsigned char *VhdPtr,int blockNo); 341 | 342 | /* 释放占据的盘块*/ 343 | void freeBlock(unsigned char *VhdPtr,int blockNo); 344 | 345 | 346 | /** 347 | * FCB 348 | * File Control Block 349 | */ 350 | 351 | /* 初始化FCB的时间和日期 */ 352 | void setFcbDateTime(FCB *fcbPtr); 353 | 354 | /* 初始化空闲的FCB */ 355 | void initFcb(FCB *fcbPtr); 356 | 357 | /* 根据文件名和类型初始化FCB */ 358 | void initFcb(FCB *fcbPtr,char *fname,char *ename,unsigned char metadata); 359 | 360 | /* 匹配文件名和文件类型是否匹配 */ 361 | int fileIsEqual(FCB * fcbPtr,char *fname,char *ename,unsigned char metadata); 362 | 363 | /* 在当前block中 申请下一个空闲的FCB | 当前的OFT 默认为目录文件 */ 364 | int getNextFcb(unsigned char * VhdPtr,int blockNo); 365 | 366 | /* 打印文件信息 | 根据文件类型选择不同的打印方式 */ 367 | void printFcbInfo(FCB *fcbPtr); 368 | 369 | 370 | void initDirectoryBlock(unsigned char *VhdPtr,int curBlockNo,int parentBlockNo); 371 | 372 | /** 373 | * FDT 374 | * Fild Descriptor Table 375 | */ 376 | 377 | void initFdt(FDT *fdtPtr); 378 | 379 | /** 380 | * OFT 381 | * Open File Table 382 | */ 383 | void initOft(OFT *oftPtr); 384 | 385 | void initOft(OFT * OftList,int curOftIndex,int parOftIndex,int fdEntryNo,FCB *fcbPtr); 386 | 387 | void initRootOft(unsigned char* VhdPtr,OFT *OftList); 388 | 389 | /* 获取父打开文件在OftList的Index*/ 390 | int getParentOft(OFT *OftList,int curOft); 391 | 392 | /* 初始化根目录文件的打开文件 */ 393 | void initRootOft(unsigned char* VhdPtr,OFT *OftList); 394 | 395 | /* 将OFT中的信息拷贝到FCB中*/ 396 | void cloneFcb2Oft(OFT *OftPtr,FCB *pcbPtr); 397 | 398 | /* 将Oft中的FCB信息保存到FCB中*/ 399 | void cloneOft2Fcb(OFT *oftPtr,FCB *fcbPtr); 400 | 401 | unsigned char * getBlockPtrByBlockNo(unsigned char *VHDPtr,int blockNo); 402 | 403 | 404 | #endif 405 | -------------------------------------------------------------------------------- /3_Simple_File_System/V0.0.2/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | #include "SysStructure.h" 3 | 4 | unsigned char Vhd[VHD_SIZE]; 5 | unsigned char VhdBuffer[VHD_SIZE]; 6 | unsigned char *VhdPtr = Vhd; 7 | unsigned char *VhdDataBlockPtr; 8 | 9 | int currOftIndex = 0; 10 | OFT OftList[OFT_NUM]; 11 | 12 | void my_sys_start(); // 进入文件系统 13 | void my_sys_exit(); // 退出文件系统 14 | void my_format(); // 磁盘格式化函数 15 | void my_mkdir(char *dirname); // 创建子目录 16 | void my_rmdir(char *dirname); // 删除子目录 17 | void my_ls(); // 显示目录中的内容 18 | void my_cd(char *dirname); // 用于更改当前目录 19 | int my_create(char *filename); // 创建文件 20 | void my_rm(char *filename); // 删除文件 21 | int my_open(char *filename); // 打开文件 22 | int my_close(int fd); // 关闭文件 23 | int my_write(int fd); // 写文件 24 | int my_read(int fd); // 读文件 25 | 26 | int do_write(int fd, char *text, int len, char wstyle); 27 | int do_read(int fd, int len, char *text); 28 | 29 | void saveHdFile(); 30 | void readHdFile(); 31 | void excuteCmd(char *cmdLine); 32 | int getIndexOfCmd(char *cmdStr); 33 | void help(); 34 | void initOftList(); 35 | 36 | 37 | 38 | 39 | int main(){ 40 | //my_format(); 41 | my_sys_start(); 42 | char cmdLine[CMD_LEN]; 43 | 44 | while(TRUE){ 45 | printf("%s > ",OftList[currOftIndex].fdt.dirName); 46 | gets(cmdLine); 47 | excuteCmd(cmdLine); 48 | } 49 | 50 | return 0; 51 | } 52 | 53 | 54 | void my_sys_start(){ 55 | 56 | readHdFile(); 57 | 58 | initOftList(); 59 | 60 | BootBlock * bootBlock = (BootBlock *)getBlockPtrByBlockNo(VhdPtr,BLOCK_INDEX_BOOT_BLOCK); 61 | 62 | VhdDataBlockPtr = bootBlock->dataBlockPtr; 63 | 64 | currOftIndex = 0; 65 | 66 | cout << bootBlock->sysInfo << endl; 67 | 68 | } 69 | 70 | 71 | void my_sys_exit(){ 72 | 73 | while(currOftIndex){ 74 | my_close(currOftIndex); 75 | } 76 | 77 | saveHdFile(); 78 | } 79 | 80 | 81 | void my_format(){ 82 | initBootBlock(VhdPtr); 83 | initFat1(VhdPtr); 84 | updateFat2(VhdPtr); 85 | initRootBlock(VhdPtr); 86 | 87 | saveHdFile(); 88 | } 89 | 90 | 91 | void my_mkdir(char *dirname){ 92 | 93 | } 94 | 95 | void my_rmdir(char *dirname){ 96 | 97 | } 98 | 99 | void my_ls(){ 100 | 101 | if(OftList[currOftIndex].fcb.metadata == MD_DATA_FILE){ 102 | cout << "Data File Could Not be ls" << endl; 103 | return; 104 | } 105 | 106 | unsigned char blockBuf[VHD_BLOCK_SIZE]; 107 | //void readVhdFile(unsigned char *VhdPtr,int blockNo,unsigned char *blockBuf){ 108 | readVhdFile(VhdPtr,OftList[currOftIndex].fcb.blockNo,blockBuf); 109 | 110 | FCB * fcbPtr = (FCB *)blockBuf; 111 | 112 | int fcbNum = VHD_BLOCK_SIZE / sizeof(FCB); 113 | for(int i=0; i< fcbNum; i++,fcbPtr++){ 114 | 115 | if(fcbPtr->isUse == TRUE){ 116 | printFcbInfo(fcbPtr); 117 | } 118 | } 119 | } 120 | 121 | void my_cd(char *dirname){ 122 | 123 | } 124 | 125 | int my_create(char *filename){ 126 | return 0; 127 | } 128 | 129 | void my_rm(char *filename){ 130 | 131 | } 132 | 133 | int my_open(char *filename){ 134 | return 0; 135 | } 136 | 137 | int my_close(int fd){ 138 | 139 | if(fd >= OFT_NUM || fd < 0){ 140 | cout << "Error : Open File Not Exist " << endl; 141 | return FAILURE; 142 | } 143 | 144 | int parentOftIndex = getParentOft(OftList,currOftIndex); 145 | if(parentOftIndex == OBJECT_NOT_FOUND){ 146 | cout << "Error : Parent File Not Exist" << endl; 147 | return FAILURE; 148 | } 149 | 150 | if(OftList[fd].fdt.isUpate == TRUE){ 151 | //TODO 152 | } 153 | return 0; 154 | } 155 | 156 | int my_write(int fd){ 157 | return 0; 158 | } 159 | 160 | int my_read(int fd){ 161 | return 0; 162 | } 163 | 164 | int do_write(int fd, char *text, int len, char wstyle){ 165 | return 0; 166 | } 167 | 168 | int do_read(int fd, int len, char *text){ 169 | return 0; 170 | } 171 | 172 | 173 | /* 保存整个虚拟磁盘文件 */ 174 | /* Save Hard Disk File */ 175 | void saveHdFile(){ 176 | FILE *filePtr = fopen(FileSysName,"w"); 177 | fwrite(VhdPtr,VHD_SIZE,1,filePtr); 178 | fclose(filePtr); 179 | } 180 | 181 | /* Read Hard Disk File*/ 182 | void readHdFile(){ 183 | 184 | FILE * sysFile = fopen(FileSysName,"r"); 185 | 186 | if(sysFile != NULL){ 187 | // Write VhdBuffer from sysFile 188 | fread(VhdBuffer,VHD_SIZE,1,sysFile); 189 | fclose(sysFile); 190 | // FileSysMagicNum: "10101010" 191 | if(memcmp(VhdBuffer,FileSysMagicNum,MAGIC_NUM_LEN) == 0){ 192 | 193 | saveVhdFile(VhdPtr,VhdBuffer); 194 | cout << "Success: FileSys.txt Read" <FUNCTION DESCRIPTION 2 | 3 | 编写三个不同的程序cmd1.c,cmd2.c,cmd3.c,每个程序输出一句话,分别编译成可执行文件cmd1,cmd2,cmd3。然后再编写一个程序,模拟shell程序的功能,能根据用户输入的字符串(表示相应的命令名),去为相应的命令创建子进程并让它去执行相应的程序,而父进程则等待子进程结束,然后再等待接收下一条命令。如果接收到的命令为exit,则父进程结束;如果接收到的命令是无效命令,则显示“Command not found”,继续等待。 4 | 5 | >COMPILE 6 | 7 | ``` 8 | make 9 | ``` 10 | 11 | >RUN 12 | 13 | ``` 14 | ./myshell 15 | ``` 16 | 17 | >Avialable Command 18 | 19 | cmd1 20 | cmd2 21 | cmd3 22 | exit 23 | 24 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_2_myshell/cmd1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("Test 1 is running.\n"); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_2_myshell/cmd2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("Test 2 is running.\n"); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_2_myshell/cmd3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("Test 3 is running.\n"); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_2_myshell/makefile: -------------------------------------------------------------------------------- 1 | all: myshell cmd1 cmd2 cmd3 2 | 3 | .PHONY : clean 4 | 5 | myshell.o : myshell.c 6 | 7 | clean : 8 | rm cmd1 cmd2 cmd3 9 | rm myshell 10 | rm *.o 11 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_2_myshell/myshell.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAX_CMD_LEN 20 9 | #define CMD_COLLECTION_LEN 4 10 | 11 | //command index 12 | #define INVALID_COMMAND -1 13 | #define EXIT 0 14 | #define CMD_1 1 15 | #define CMD_2 2 16 | #define CMD_3 3 17 | 18 | //bool 19 | #define TRUE 1 20 | 21 | char *cmdStr [CMD_COLLECTION_LEN ]= {"exit","cmd1","cmd2","cmd3"}; 22 | 23 | 24 | /* 25 | * FUNCTION 26 | * check if the command is validate and get cmd Index 27 | * PARAM 28 | * cmd [string ] command line 29 | * RETURN 30 | * -1 : invalid 31 | * else : index of cmdCollection 32 | */ 33 | 34 | int getCmdIndex(char *cmd) 35 | { 36 | int i; 37 | 38 | for(i=0;isleep waiting 128 | while(TRUE) 129 | { 130 | printf("\n-------F : Please Input your command -------\nuser&:"); 131 | 132 | scanf("%s",cmdStr); 133 | cmdIndex = getCmdIndex(cmdStr); 134 | runCMD(cmdIndex); 135 | 136 | wait(0); //TODO 137 | printf("-------F : waiting for next command -------\n"); 138 | } 139 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_3_Pipe_Communication/README.md: -------------------------------------------------------------------------------- 1 | >FUNCTION DESCRIPTION 2 | 3 | 由父进程创建一个管道,然后再创建2个子进程,并由这两个兄弟进程利用管道进行进程通信:子进程1使用管道的写端,子进程2使用管道的读端。通信的具体内容可根据自己的需要随意设计,要求能试验阻塞型读写过程中的各种情况。运行程序,观察各种情况下,进程实际读写的字节数以及进程阻塞唤醒的情况。 4 | 5 | >COMPILE 6 | 7 | ``` 8 | make 9 | ``` 10 | 11 | >RUN 12 | 13 | ``` 14 | ./pipe_communication 15 | ``` 16 | 17 | >output 18 | 19 | ``` 20 | Write Process : Wanna input 70 characters 21 | Write Process : Wrote in 70 characters ... 22 | Write Process: Sleep - 10 Seconds ... 23 | Read Process : Time 1 24 | Read Process : Wanna read 50 characters. 25 | Read Process : Read 50 characters 26 | Read Process : Time 2 27 | Read Process : Wanna read 50 characters. 28 | Read Process : Read 20 characters 29 | Read Process : Time 3 30 | Read Process : Wanna read 70 characters. 31 | Write Process: Wake up then Why not rewrite 70 characters ? 32 | Write Process : Wanna input 70 characters 33 | Write Process : Wrote in 70 characters ... 34 | Read Process : Read 70 characters 35 | Write Process : Done 36 | -------------End of Program----------- 37 | ``` 38 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_3_Pipe_Communication/makefile: -------------------------------------------------------------------------------- 1 | pipe_communication : pipe_communication.o 2 | 3 | .PHONY : clean 4 | 5 | clean: 6 | rm *.o 7 | rm pipe_communication 8 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_3_Pipe_Communication/pipe_communication.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #define MAXSIZE 100 12 | #define READ_NUM 50 13 | #define WRITE_NUM 70 14 | 15 | void InitStr(char * text,int len) 16 | { 17 | int i; 18 | char str[MAXSIZE]; 19 | 20 | for(i = 0; i Write 105 | { 106 | WriteProcess(fd); 107 | } 108 | else //father interprocess 109 | { 110 | //create a new child interprocess: read 50 111 | if((pid = fork()) < 0) 112 | { 113 | fprintf(stderr, " Fork Error : %s \n",strerror(errno) ); 114 | exit(EXIT_FAILURE); 115 | } 116 | if(pid == 0) // child interprocess 2 => Read 117 | { 118 | ReadProcess(fd); 119 | } 120 | else //father interprocess 121 | { 122 | wait(0); 123 | wait(0); 124 | printf("-------------End of Program-----------\n"); 125 | return 0; 126 | } 127 | 128 | } 129 | 130 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_4_message_queue/README.md: -------------------------------------------------------------------------------- 1 | >Function 2 | 3 | 编写程序创建两个线程:sender线程和receive线程,其中sender线程运行函数sender(), 4 | 它创建一个消息队列,然后,循环等待用户通过终端输入一串字符,将这串字符通过消息队列发送给receiver线程, 5 | 直到用户输入“exit”为止;最后,它向receiver线程发送消息“end”,并且等待receiver的应答,等到应答消息后, 6 | 将接收到的应答信息显示在终端屏幕上,删除相关消息队列,结束程序的运行。Receiver线程运行receive(), 7 | 它通过消息队列接收来自sender的消息,将消息显示在终端屏幕上,直至收到内容为“end”的消息为止,此时, 8 | 它向sender发送一个应答消息“over”,结束程序的运行。 9 | 使用无名信号量实现两个线程之间的同步与互斥。 10 | 11 | 12 | >使用说明 13 | 14 | gif动画演示 15 | [4_4 message queue 例程演示](http://www.jianshu.com/p/b4a6699ede6a) 16 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_4_message_queue/makefile: -------------------------------------------------------------------------------- 1 | message_queue : message_queue.o 2 | cc -pthread -o message_queue message_queue.o 3 | 4 | .PHONY : clean 5 | 6 | 7 | clean: 8 | rm message_queue 9 | rm *.o 10 | 11 | 12 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_4_message_queue/message_queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define TRUE 1 16 | 17 | 18 | #define BUF_SIZE 255 19 | #define PERM S_IRUSR|S_IWUSR 20 | #define KEY_NUM 1000 21 | 22 | 23 | typedef struct msgbuf msgbuf; 24 | 25 | struct msgbuf 26 | { 27 | long mtype; 28 | char mtext[BUF_SIZE + 1]; 29 | }; 30 | 31 | 32 | //semaphore and mutex 33 | sem_t full; 34 | sem_t empty; 35 | sem_t mutex; 36 | 37 | //pthread 38 | pthread_t write_pid; 39 | pthread_t read_pid; 40 | 41 | 42 | key_t key; 43 | //message 44 | int msgid; 45 | 46 | struct msgbuf msg; 47 | 48 | 49 | void Init() 50 | { 51 | /// init semaphore 52 | sem_init(&full,0,0); 53 | sem_init(&empty,0,1); 54 | sem_init(&mutex,0,1); 55 | 56 | key = KEY_NUM; 57 | 58 | // Create Message Queue 59 | if((msgid = msgget(key,PERM|IPC_CREAT)) == -1) 60 | { 61 | fprintf(stderr, "Create Message Queue Error %s\n",strerror(errno) ); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | 66 | 67 | } 68 | 69 | 70 | void * ReadProcess(void *arg) 71 | { 72 | msgbuf msg; 73 | //init msg 74 | msg.mtype = 1; 75 | while(TRUE) 76 | { 77 | 78 | sem_wait(&full); 79 | sem_wait(&mutex); 80 | 81 | //receive message from message queue 82 | msgrcv(msgid,&msg,sizeof(msgbuf),1,0); 83 | 84 | //detect for end 85 | if(strcmp(msg.mtext,"end") == 0) 86 | { 87 | msg.mtype = 2; 88 | strncpy(msg.mtext,"over",BUF_SIZE); 89 | msgsnd(msgid,&msg,sizeof(msgbuf),0); 90 | break; 91 | } 92 | 93 | //print message 94 | printf("RP: [message received] %s\n\n",msg.mtext); 95 | 96 | sem_post(&empty); 97 | sem_post(&mutex); 98 | } 99 | 100 | exit(EXIT_SUCCESS); 101 | } 102 | 103 | void * WriteProcess(void *arg) 104 | { 105 | 106 | char input[50]; 107 | msgbuf msg; 108 | msg.mtype = 1; 109 | 110 | while (TRUE) 111 | { 112 | 113 | 114 | //semaphore 115 | sem_wait(&empty); 116 | sem_wait(&mutex); 117 | 118 | printf("WP: Please Input the message you want to send.\n"); 119 | scanf("%s",input); 120 | 121 | if(strcmp(input,"exit") == 0) 122 | { 123 | strncpy(msg.mtext,"end",BUF_SIZE); 124 | msgsnd(msgid,&msg,sizeof(msgbuf),0); 125 | break; 126 | } 127 | strncpy(msg.mtext,input,BUF_SIZE); 128 | msgsnd(msgid,&msg,sizeof(msgbuf),0); 129 | 130 | printf("WP: [message sent] %s\n",msg.mtext ); 131 | 132 | //semaphore 133 | sem_post(&full); 134 | sem_post(&mutex); 135 | } 136 | 137 | 138 | 139 | // Clear Node 140 | memset(&msg,'\0',sizeof(msgbuf)); 141 | // Block ,waiting for msg with type = 2 142 | msgrcv(msgid,&msg,sizeof(msgbuf),2,0); 143 | printf("WP: [message sent]%s\n",msg.mtext ); 144 | 145 | //Remove Message Queue 146 | if( msgctl (msgid,IPC_RMID,0) == -1) 147 | { 148 | fprintf(stderr, "Remove Message Queue Error%s\n", strerror(errno)); 149 | exit(EXIT_FAILURE); 150 | } 151 | exit(EXIT_SUCCESS); 152 | } 153 | 154 | int main() 155 | { 156 | 157 | 158 | Init(); 159 | 160 | pthread_create(&write_pid,NULL,WriteProcess,NULL); 161 | pthread_create(&read_pid,NULL,ReadProcess,NULL); 162 | 163 | //waiting for the thread end 164 | pthread_join(write_pid,NULL); 165 | pthread_join(read_pid,NULL); 166 | 167 | 168 | printf("Main Function End...\n"); 169 | 170 | return 0; 171 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_5_shared_memory/README.md: -------------------------------------------------------------------------------- 1 | > 功能描述 2 | 3 | 编写程序sender,它创建一个共享内存,然后等待用户通过终端输入一串字符,并将这串字符通过共享内存发送给receiver;最后,它等待receiver的应答,等到应答消息后,将接收到的应答信息显示在终端屏幕上,删除共享内存,结束程序的运行。编写receiver程序,它通过共享内存接收来自sender的消息,将消息显示在终端屏幕上,然后再通过该共享内存向sender发送一个应答消息“over”,结束程序的运行。使用无名信号量或System V信号量实现两个进程对共享内存的互斥使用。 4 | 5 | 6 | > step 1 7 | 8 | ``` 9 | make 10 | ``` 11 | 12 | > step 2 13 | 14 | Initialization Semaphpre and Message Queue 15 | 16 | ``` 17 | ./init 18 | ``` 19 | 20 | Send message : input the message you want to send 21 | ``` 22 | ./sender 23 | ``` 24 | 25 | Recevier message 26 | ``` 27 | ./recevier 28 | ``` 29 | 30 | makefile的使用 31 | 32 | [makefile 同时生成多个可执行文件](http://www.jianshu.com/p/f1d95969e7df) 33 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_5_shared_memory/common.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | /* 4 | key_t GetKey(const char * pathname) 5 | { 6 | //int fd = open(pathname,O_CREAT,0666); 7 | int fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU); 8 | if(fd < 0) 9 | { 10 | perror("open file error"); 11 | return -1; 12 | } 13 | 14 | close(fd); 15 | 16 | return ftok(pathname,0); 17 | } 18 | 19 | */ 20 | 21 | int GetShmId(key_t key) 22 | { 23 | int shmid; 24 | 25 | shmid = shmget(key,SHM_SIZE,IPC_CREAT|0666); 26 | if(shmid < 0) 27 | { 28 | perror("Receiver: Shmget Error"); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | return shmid; 33 | } 34 | 35 | /* 36 | * create mutex + semaphore 37 | * init those value 38 | */ 39 | void SemInit() 40 | { 41 | /* 42 | * Funtion Prototype: 43 | * 44 | * sem_t *sem_open(const char *name, int oflag, 45 | * mode_t mode, unsigned int value); 46 | * 47 | * name : MUTEX_NAME "mutex_shm" 48 | * oflag : O_CREAT Create and initialize it if not exist 49 | * mode_t : file perssion -rw-r--r-- 50 | * value : 1 51 | */ 52 | if((sem_open(MUTEX_NAME,O_CREAT,0644,1)) < 0) 53 | { 54 | perror("sem_open"); 55 | exit(EXIT_FAILURE); 56 | } 57 | 58 | if((sem_open(FULL_NAME,O_CREAT,0644,0)) < 0){ 59 | perror("sem_open"); 60 | exit(EXIT_FAILURE); 61 | } 62 | } 63 | 64 | 65 | /* 66 | * close and unlink semaphore that we crated 67 | */ 68 | void SemDestroy() 69 | { 70 | sem_t * mutexPtr = sem_open(MUTEX_NAME,O_CREAT); 71 | sem_t * fullPtr= sem_open(FULL_NAME,O_CREAT); 72 | 73 | /* Destroy mutex */ 74 | sem_close(mutexPtr); // int sem_close(sem_t *sem); 75 | sem_unlink(MUTEX_NAME); // int sem_unlink(const char *name); 76 | 77 | /* Destory full*/ 78 | sem_close(fullPtr); 79 | sem_unlink(FULL_NAME); 80 | } 81 | 82 | 83 | void P(sem_t *semPtr) 84 | { 85 | sem_wait(semPtr); //int sem_wait(sem_t *sem); 86 | } 87 | 88 | void V(sem_t *semPtr) 89 | { 90 | sem_post(semPtr); //int sem_post(sem_t *sem); 91 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_5_shared_memory/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMMON_H_ 2 | #define _COMMON_H_ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | 23 | static const char * MUTEX_NAME = "mutex_shm"; 24 | static const char * FULL_NAME = "full_shm"; 25 | //static const char * PATH_NAME = "tmp/shmtemp"; 26 | 27 | 28 | //constant define 29 | #define SHM_SIZE 1024 30 | 31 | #define KEY_NUM 1000 32 | 33 | /* 34 | key_t GetKey(const char * pathname); 35 | */ 36 | 37 | int GetShmId(key_t key); 38 | /* 39 | * create mutex + semaphore 40 | * init those value 41 | */ 42 | void SemInit(); 43 | 44 | void SemDestroy(); 45 | 46 | void P(sem_t *sem); 47 | 48 | void V(sem_t *sem); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_5_shared_memory/init.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | int main(int argc, char const *argv[]) 4 | { 5 | key_t key; 6 | int semid; //semaphore id 7 | int shmid; //shared memory id 8 | 9 | 10 | /* Create key*/ 11 | key = KEY_NUM; 12 | 13 | /* Initialize Semaphore*/ 14 | SemInit(); 15 | 16 | /* TODO Initialize Shared Memory*/ 17 | GetShmId(key); 18 | 19 | printf("End of initialize\n"); 20 | return 0; 21 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_5_shared_memory/log.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mushroom-x/OS-Assignment-2016/3166ae82c70b4d9a136e06735163e54194b1085a/4_Linux_Progress_Control/4_5_shared_memory/log.txt -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_5_shared_memory/makefile: -------------------------------------------------------------------------------- 1 | all : init sender receiver 2 | .PHONY : clean 3 | 4 | 5 | init : init.o common.o 6 | cc -pthread -o init init.o common.o 7 | 8 | sender : sender.o common.o 9 | cc -pthread -o sender sender.o common.o 10 | 11 | receiver : receiver.o common.o 12 | cc -pthread -o receiver receiver.o common.o 13 | 14 | 15 | init.o : common.h 16 | 17 | sender.o : common.h 18 | 19 | receiver.o : common.h 20 | 21 | clean : 22 | rm init 23 | rm receiver 24 | rm sender 25 | rm *.o 26 | 27 | 28 | -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_5_shared_memory/receiver.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | 4 | //key 5 | key_t key; 6 | 7 | //shared memory 8 | int shmid; 9 | char * shmptr; 10 | char result[SHM_SIZE]; 11 | 12 | //semaphore 13 | sem_t * full; 14 | sem_t * mutex; 15 | //semaphore 16 | 17 | 18 | void Init() 19 | { 20 | key = KEY_NUM; //init key 21 | shmid = GetShmId(key); // init shared memory 22 | shmptr = shmat(shmid,NULL,0); // attach segement to vitural ...? 23 | //semaphore init 24 | full = sem_open(FULL_NAME,O_CREAT); 25 | mutex = sem_open(MUTEX_NAME,O_CREAT); 26 | } 27 | 28 | void ReadMessage() 29 | { 30 | P(full); 31 | P(mutex); 32 | strcpy(result,shmptr); 33 | V(mutex); 34 | } 35 | 36 | int main(int argc, char const *argv[]) 37 | { 38 | 39 | 40 | Init(); 41 | 42 | /*waiting for user to input message*/ 43 | ReadMessage(); 44 | 45 | printf("Receiver : message is %s\n",result); 46 | SemDestroy(); 47 | printf("Receiver : Process End \n"); 48 | return 0; 49 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/4_5_shared_memory/sender.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | 4 | //key 5 | key_t key; 6 | 7 | //shared memory 8 | int shmid; 9 | char * shmptr; 10 | char input[SHM_SIZE]; 11 | 12 | //semaphore 13 | sem_t * full; 14 | sem_t * mutex; 15 | //semaphore 16 | 17 | 18 | void Init() 19 | { 20 | key = KEY_NUM; //init key 21 | shmid = GetShmId(key); // init shared memory 22 | shmptr = shmat(shmid,NULL,0); // attach segement to vitural ...? 23 | //semaphore init 24 | full = sem_open(FULL_NAME,O_CREAT); 25 | mutex = sem_open(MUTEX_NAME,O_CREAT); 26 | } 27 | 28 | void SaveMessage() 29 | { 30 | 31 | P(mutex); 32 | strcpy(shmptr,input); 33 | V(mutex); 34 | 35 | V(full); 36 | } 37 | 38 | int main(int argc, char const *argv[]) 39 | { 40 | 41 | 42 | Init(); 43 | 44 | /*waiting for user to input message*/ 45 | scanf("%s",input); //input message from shell 46 | // TODO input a whole line 47 | SaveMessage(); 48 | 49 | printf("Sender: Process End\n"); 50 | return 0; 51 | } -------------------------------------------------------------------------------- /4_Linux_Progress_Control/README.txt: -------------------------------------------------------------------------------- 1 | [Assignment 4 Details](http://www.jianshu.com/p/3680ed5eb3da) 2 | 3 | lalala 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Scorpion-X 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OS-Assignment-2016 2 | KEY WORD : 操作系统 课程设计 参考代码 杭电 3 | 4 | >声明:代码仓库建立的目的是帮助更多的同学体会到编写操作系统文件的乐趣,强烈建议大家都尝试自己写一下代码。 5 | 文件系统为完工,其他的都可以正常使用 6 | Operating System Assignment in HDU. Teacher:ZWH 7 | 8 | @Author Scorpion 9 | 10 | @PowerBy ASA 11 | 12 | @University HangZhou Dianzi University | 杭州电子科技大学 13 | 14 | 15 | > 估计好多小伙伴想加我QQ,嘿嘿 244561792, 希望我们可以共同优化 16 | --------------------------------------------------------------------------------