Try   HackMD

2021q1 Homework7 (quiz7)

contributed by < hankluo6 >

GitHub

2021-04-06

第 7 週測驗題

Problem 1

/* Recursively run right-most part of the command line printing output to the
 * file descriptor @t
 */
static void run(char *c, int t)
{
    char *redir_stdin = NULL, *redir_stdout = NULL;
    int pipefds[2] = {0, 0}, outfd = 0;
    char *v[99] = {0};
    char **u = &v[98]; /* end of words */
    
    for (;;) {
        c--;
        if (is_delim(*c)) /* if NULL (start of string) or pipe: break */
            break;
        if (!is_special(*c)) {
            /* Copy word of regular chars into previous u */
            *u = c;
        }
        if (is_blank(*c)) {
            *c = '\0';
            u--;
        }
        if (is_redir(*c)) { /* If < or > */
            if (*c == '<')
                redir_stdin = *u;
            else
                redir_stdout = *u;
            if ((u - v) != 98)
                u++;
        }
    }
    if ((u - v) == 98) /* empty input */
        return;
    printf("%s\n", u[1]);
    if (!strcmp(*u, "cd")) { /* built-in command: cd */
        fatal(chdir(u[1]), 0);
        return; /* actually, should run() again */
    }

    if (*c) {
        pipe(pipefds);
        outfd = pipefds[1]; /* write end of the pipe */
    }

    pid_t pid = fork();
    if (pid) { /* Parent or error */
        fatal(pid, 1);
        if (outfd) {
            run(c, outfd);     /* parse the rest of the cmdline */
            close(outfd);      /* close output fd */
            close(pipefds[0]); /* close read end of the pipe */
        }
        wait(0);
        return;
    }

    if (outfd) {
        dup2(pipefds[0], 0); /* dup read fd to stdin */
        close(pipefds[0]);   /* close read fd */
        close(outfd);        /* close output */
    }

    if (redir_stdin) {
        close(0); /* replace stdin with redir_stdin */
        fatal(open(redir_stdin, 0), 1);
    }

    if (t) {
        dup2(t, 1); /* replace stdout with t */
        close(t);
    }

    if (redir_stdout) {
        close(1);
        fatal(creat(redir_stdout, 438), 1); /* replace stdout with redir */
    }
    fatal(execvp(*u, u), 1);
}

Problem 2

static void dequeue(queue_t *q, int *fd)
{
    node_t *old_head;
    pthread_mutex_lock(q->head_lock);
    /* Wait until signaled that queue is non_empty.
     * Need while loop in case a new thread manages to steal the queue
     * element after the waiting thread is signaled, but before it can
     * re-acquire head_lock.
     */
    while (!q->size) 
        pthread_cond_wait(q->non_empty, q->head_lock);
    old_head = q->head->next;
    q->head->next = old_head->next;
    if (!old_head->next)
        q->tail = q->head;
    q->size--;
    *fd = old_head->fd;
    pthread_mutex_unlock(q->head_lock);
    free(old_head);
}
  1. 執行緒函式 greeter_routine 和 worker_routine 在上述網頁伺服器中,分別負責什麼功能?

greeter_routine 接收 http 請求,worker_routine 則用來 parse 請求,並回傳對應的訊息。

  1. enqueue 和 dequeue 是單向鏈結串列 (singly-linked list) 所實作的佇列 (queue) 裡頭的基本操作,你如何驗證自己的實作能在並行環境正確無誤?

對每項 queue 操作皆確保持有 lock。

tags: linux2021