【問題1】
Write a C program that creates a new process to copy the files using the sample
MyCopy. This program should spawn a new process using fork system call. Then use
execlp to execute MyCopy program. The source and destination file names presented
as command-line arguments should be passed to execlp as system call arguments. The
main process waits for completion of copy operation using wait system call. Use
various system calls for time to calculate the execute time of this program.
【解答】
MyCopy.c
#include "header.h" int main(int argc, char* argv[ ]){ if(argc!=3){ // parameter error printf("Wrong Usage: MyCopy <source file name> <target file name>\n"); exit(-1); } FILE *src; clock_t start,end; // the beginning and the end of the time double elapsed; // period of time struct timeval startTime, endTime; struct timezone tz; long run_time_in_microseconds; start = clock(); //time count gettimeofday(&startTime, &tz); src = fopen(argv[1],"r"); //Open source file //Check for file error if(src==NULL){ printf("Error: Could not open file '%s'.\n",argv[1]); exit(-1); } FILE *dest; dest = fopen(argv[2],"w+"); //Open destination file //Check for file error if(dest==NULL){ printf("Error:Could not open file '%s'.\n",argv[2]); fclose(src); exit(-1); } char c; //copy use fgetc fputc while(!feof(src)){ c = fgetc(src); if(!feof(src)) fputc(c,dest); } fclose(src); fclose(dest); end = clock(); gettimeofday(&endTime, &tz); elapsed = ((double)(end-start))/CLOCKS_PER_SEC*1000; // time in millisecond printf("MyCopy Time used:%f millisecond\n",elapsed); run_time_in_microseconds = endTime.tv_usec - startTime.tv_usec; printf("Time used: %ld microseconds.\n",run_time_in_microseconds); exit(0); }ForkCopy.c
#include "header.h" int main(int argc, char *argv[ ]) { pid_t ForkPID; ForkPID = fork(); // Using system call "fork" to create a new process if (ForkPID>0){ // parent process int status = 0; wait(&status); exit(0); }else if (ForkPID==0){ // child process execlp("./MyCopy", argv[0], argv[1], argv[2], NULL); }else{ // fail to fork a child process printf("Error: Failed to fork.\n"); exit(-1); } }
【問題2】
Make the mini shell (from the sample MyShell) a little more powerful by allowing
arguments to the commands. For example, it should be able to execute commands
such as more filename and ls -l ~/tmp etc.
【解答】
MoreShell.c
#include "header.h" int main(int argc, char* argv[ ]){ if(argc!=1){ printf("Wrong Usage: MyShell\n"); exit(-1); } //To start the mini-shell, you should call ./MoreShell printf("PID:%d, MyShell (\"exit\" for end) >>", getpid()); //wait for the user to input some commands char *buffer=NULL; size_t len=0; while (1){ getline(&buffer, &len, stdin); //read the whole line buffer[strlen(buffer)-1]='\0'; //replace the character '\n' by '\0' to indicate the end of the command buffer if (!strcmp(buffer, "exit")) { free(buffer); break; } //if user's command is 'exit', the mini-shell is terminated. char **argvs = (char **) malloc (sizeof(char *)); //ready to receive arguments of the command(seperated by whitespace) int count=0; //number of arguments //seperate the command using the way proposed by ppt char *p=strtok(buffer, " "); while (p!=NULL && strcmp(p,"|")!=0) { argvs[count]=p; count ++; argvs = realloc(argvs, (count+1) * sizeof(char *)); p = strtok(NULL," "); } argvs[count]=NULL; //the last argument should be 'NULL' pid_t ForkPID=fork(); //use system call 'fork' to create a new process for executing the given command int status; switch(ForkPID){ case -1: //failed to create the child process printf("Error:Failed to fork.\n"); break; case 0: //child process, first executes the given command then receives the status if (execvp(argvs[0],argvs)==-1) printf("Error: running command: '%s'\n", argvs[0]); exit(0); break; default: //parent process, waiting for child process to be finished wait(&status); } printf("PID:%d, MyShell (\"exit\" for end) >>", getpid()); //waiting for the user to input next command } }【問題3】
Modify the sample MyThread using two semaphores to control the program then
let thread 1 modify number before thread 2.
【解答】
MoreThread.c
#include "header.h" int number;//protected external value sem_t sem_id1, sem_id2; //thread 1 void *thread_one_fun(void*argv){ sem_wait(&sem_id1); //get the acces to number printf("Thread 1 is going to change the number.\n"); number++; printf("Thread 1: number = %d \n",number); sem_post(&sem_id2); //let thread two go after thread one has finished pthread_exit(NULL); } //thread 2 void *thread_two_fun(void*argv){ sem_wait(&sem_id2); //if thread two executes first, it will be blocked for sem_id2 is 0 at the beginning. printf("Thread 2 is going to change the number.\n"); number--; printf("Thread 2: number = %d \n",number); sem_post(&sem_id1); //after thread two has finished, post sem_id1 pthread_exit(NULL); } int main(int argc, char* argv[]){ number = 1; printf("main function: number=1 at the beginning.\n"); sem_init(&sem_id1,0,1); //initialize sem_id1 to be 1 sem_init(&sem_id2,0,0); //initialize sem_id2 to be 0 pthread_t pt1,pt2; int id[2]; id[0] = 1; id[1] = 2; int rc; rc=pthread_create(&pt1,NULL,thread_one_fun,&id[0]); rc=pthread_create(&pt2,NULL,thread_two_fun,&id[1]); void* status1; rc = pthread_join (pt1, &status1); if (rc) printf("ERROR: return code from pthread_join(pt1) is %d\n", rc); void* status2; rc = pthread_join (pt2, &status2); if (rc) printf("ERROR: return code from pthread_join(pt2) is %d\n", rc); sem_destroy(&sem_id1); sem_destroy(&sem_id2); printf("main function terminated.\n"); exit(0); }【測試結果】