【问题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 usevarious 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 } }
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); }