Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

A simple Linux shell: Your shell should repeatedly display a prompt and allow a user to enter a command to run. Your shell is supposed

    1. A simple Linux shell: Your shell should repeatedly display a prompt and allow a user to enter a command to run.  Your shell is supposed to read the input from system standard input, parse the line with command and arguments, and execute. You must only use fork() and execv() system calls to support the shell command execution.
      • Your shell should find the internal commands first (described below). If not found, it should search the directories in the shell's pathname environment.
      • You are not allowed to use system(), as it invokes the system's /bin/sh shell. You cannot use execlp() or execvp(), because your shell has its own pathname variable.
      • By convention, the command arguments are separated by white spaces. Your shell does not need to handle special characters, such as <, >, |, &, and so on.
      • Internal Commands: Implement the following 3 internal commands (running in the main process rather than the child process).
        • cd: is a command, obviously, to change directories. You are required to use chdir() system call.
        • path: is not only a command to show the current pathname variable content (if no argument is provided), but also a utility to modify (either add or remove) the pathname variable content.
          • path   +   /abc/def  should append the pathname "/abc/def" to the pathname variable, which is a string. E.g., "/bin:/sbin:/abc/def" (where ':' is a delimiter).
          • path   -   /abc/def  should remove the pathname "/abc/def" from the existing pathname variable.
        • quit: is a command to leave the shell.
      • Give the above path command, you are NOT ALLOWED to use following functions to access a file name or obtain the pathname information: access(), getenv(), setenv(), etc.
      • A string parser: A (string) parser is a function that breaks an input string into parts, such as commands and parameters, which can be managed by other programming components. In this project, you are highly suggested to implement a string parser. The functionality and the structure of your string parser should be organized in the following steps.
        1. Keyboard input: you are required to use fgets(buf, 256, stdin) library function to take the keyboard input, where buf is a char pointer (to be declared), 256 is the command length limit, and stdin the system standard input.
        2. Parsing: given a command string stored in buf, suppose the content can be represented as "cmd  arg1  arg2  arg3 ...".
          1. your parser first breaks the string into a string array, for example token[]. The size of token[] should always be the number of words plus one. For example, given a command with 3 argument, your token[] size should be 1+3+1=5, where token[4] stores NULL.
          2. your parser then checks whether "cmd" (stored in token[0]) is an internal command (as described above). If it is, then you perform this internal command in the parent process.
          3. If it is not an internal command, then you must use fork()/execv() pair to arrange "cmd" to be executed in a child process.  If "cmd" cannot be found (e.g., due to a typo), you need to output corresponding error message to the screen.
    2. A multi-threading application (messageprint.c): in this exercise, you will write a simple Message Print program (similar to the following example code)  in which multiple threads print messages with a controlled order. In particular, we want threads with an even (thread) ID to print first, and those threads with an odd (thread) ID to print after all the even threads have done the printing.  Note that all threads will start in a random order, we must have odd threads wait until all the even threads have printed.
      • To achieve the events-print-first functionality, you need to use the condition variable routines in the PThread library:
        •  
          • pthread_cond_wait(pthread_cond_t *condition, pthread_mutex_t *lock);
          • pthread_cond_signal(pthread_cond_t *condition);
          • pthread_cond_broadcast(pthread_cond_t *condition);
          • The pthread_cond_wait routine will put the caller thread to sleep on the condition variable condition and release the mutex lock, guaranteeing that when the subsequent line is executed after the caller has woken up, the caller will hold lock. The pthread_cond_signal routine wakes up one thread off of the condition variable condition, and pthread_cond_broadcast wakes up all threads that are sleeping on condition variable condition. IMPORTANT: to call any of the above routines, the caller must first hold the lock that is associated with that condition variable.
          • You'll need to have these global variables in your messageprint.c file:
            • pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
            • pthread_cond_t CV = PTHREAD_COND_INITIALIZER;
            • int number_evens_finished = 0;
          • You will need to use pthread_mutex_lock, pthread_mutex_unlock, pthread_cond_wait, and pthread_cond_broadcast. Do not use pthread_cond_signal.
      • Input/Output requirements:
        • Input: your message print application (messageprint) should take an integer command-line augument that allows the evaluator (TA) to specify the number of threads to be created.  Your program should support at least 20 threads. For example:
          • $ messageprint 20
        • Output: each created thread should print out one or two lines of messages.  Again, all odd numbered threads must print after the even threads have done the printing.  Avoid printing 3 or more lines of message for each thread.
    3. Makefile and README: provide  a makefile so "make" command will produce the executable.  You are required to write a README file (text format only) that describes your project design details and the compile & execution sequence (with the commands).  In particular, please explicitly state which part, if there is any, does not work and the possible reasons why that module does not work.  For those working modules, please provide a test run output.

    A simple multi-threading program example, which creates 20 threads, each of which prints a hello message.

    #define NUM_THREADS 20
    void *printMessage(void *t) {
      int i;
      long tid;
      double res = 0.0;
      tid = (long) t;
      printf("thread %ld starting...\n", tid);
      for (i=0; i<100000; i++) {
        res += sqrt(i) * tan(i); // doing some meaningless computation
      }
      printf("thread %ld done. Result = %e\n", tid, res);
      pthread_exit((void *) t);
    }

    int main(int argc, char *argv[]) {
      pthread_t thread[NUM_THREADS];
      int rc;
      long t;

      for (t=0; t < NUM_THREADS; t++) {
        printf("hello: creating thread %ld\n", t);
        rc = pthread_create(&thread[t], NULL, printMessage, (void *)t);
        if (rc) {
          printf("error: return code from pthread_create() is %d\n", rc);
          exit(-1);
        }
      }
      pthread_exit(NULL);
    }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Introduction to Java Programming, Comprehensive Version

Authors: Y. Daniel Liang

10th Edition

133761312, 978-0133761313

More Books

Students also viewed these Algorithms questions

Question

Signals are conveyed through a variety of channels.

Answered: 1 week ago