联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-23:00
  • 微信:codinghelp

您当前位置:首页 >> C/C++编程C/C++编程

日期:2019-04-26 10:56

COMP 321

April 24, 2019

Questions on this exam may refer to the textbook as well as to the manual pages on CLEAR.

Therefore, you should not start the exam until you are in a position to access both.

As a reminder, the notation fdopen(3) means that the manual page for the function fdopen

can be displayed with the command man 3 fdopen.

You may review any section of the textbook and any manual page on CLEAR during the exam,

and not just those explicitly referenced by the questions. Moreover, you may review any of the

lecture notes, labs, and assignments that the instructors have provided to you or any notes that

you have taken for this class. You may also use CLEAR to develop and test your C code for this

exam. You may not consult any other sources of information, including other textbooks, web sites,

or people, aside from the instructors.

This is a 5 hour exam. You must take the exam in one continuous block of time. You may

take one break of up to one hour during the exam. Your exam period begins as soon as you look

at any page of the exam other than these instructions. Indicate in your exam submission the date

and time at which you start the exam, the time at which you start your break, the time at which

you end your break, and the time at which you end the exam.

Once you begin the exam, you may not discuss the exam with anyone other than the instructors

until the end of the finals period. If you find anything in the exam to be ambiguous, clearly state

all of the assumptions that you are making in solving the problem.

All of the questions have brief answers of either a single paragraph or a single C function that

is small in size. Always explain your answer and comment any C code you write to explain what

it does. Most of your score will be determined by your explanation. Turn in your answers through

Canvas by 5PM on Wednesday, May 1st. Submit your answers in the form of a text file (.txt),

following the same formatting guidelines as for your programming assignments.

1 of 8

1. [20 points] Consider the following program.

#include "csapp.h"

void

two(void){Write(STDOUT_FILENO, "2", 1);}int

main(void)

{if (Fork() == 0)atexit(two);

if (Fork() == 0)

Write(STDOUT_FILENO, "0", 1);

else

Write(STDOUT_FILENO, "1", 1);

exit(0);}

Determine which of the following outputs are possible. Explain your answer. Note: The

atexit(3) function takes a pointer to a function and adds it to a list of functions (initially

empty) that will be called when the exit(3) function is called.

A. 001212

B. 010212

C. 022110

D. 102120

E. 112002

F. 210120

Suppose Write is replaced by printf. For example, Write(STDOUT FILENO, "2", 1); becomes

printf("2");. How would this change affect your answer?

2 of 8

2. [20 points] Modify the program cpfile.c from Figure 10.5 of the textbook so that it takes

an optional command-line argument that is a file name. If a file name is given on the command

line, then copy the contents of that file to standard output; otherwise, copy standard input

to standard output as before. The twist is that your solution must use the original copy loop

(lines 9-11 in the textbook) for both cases. You are only allowed to insert code. You are not

allowed to change any of the existing code. The program cpfile.c is shown below for your

convenience.

#include "csapp.h"

int main(int argc, char **argv)

{

int n;

rio_t rio;

char buf[MAXLINE];

Rio_readinitb(&rio, STDIN_FILENO); // line 9

while ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) // line 10

Rio_writen(STDOUT_FILENO, buf, n); // line 11

}

3 of 8

3. [20 points] Consider the function fgets and one of its possible implementations.

/*

* This implementation of fgets() is adapted from the first edition

* of ‘‘The C Programming Language’’ by Kernighan and Ritchie.

*/

char *

fgets(char *string, int size, FILE *stream)

{

char *cs;

int c;

cs = string;

while (--size > 0 && (c = getc(stream)) != EOF)

if ((*cs++ = c) == ’\n’)

break;

*cs = ’\0’;

return ((c == EOF && cs == string) ? NULL : string);

}

Using alarm(2) and non-local jumps, write a version of the function fgets, called tfgets,

that times out after 5 seconds. The function tfgets accepts the same inputs as fgets. If

the user doesn’t type an input line within 5 seconds, tfgets returns NULL. Otherwise, it

returns a pointer to the input line.

4 of 8

4. [20 points] In this problem, you will examine the code generated by a C compiler for functions

that have structures as arguments and return values, and from this learn how these language

features are typically implemented.

The following C code has a function compute having structures as arguments and return

values, and a function caller that calls compute.

struct str1 {

long a;

long b;

long *p;

};

struct str2 {

long sum;

long diff_a_b;

long diff_b_p;

};

struct str2

compute(struct str1 s1)

{

struct str2 result;

result.sum = s1.a + s1.b + *s1.p;

result.diff_a_b = s1.a - s1.b;

result.diff_b_p = s1.b - *s1.p;

return (result);

}

long

caller(long x, long y, long z)

{

struct str1 s1;

struct str2 s2;

s1.a = x;

s1.b = y;

s1.p = &z;

s2 = compute(s1);

return (s2.sum + s2.diff_a_b + s2.diff_b_p);

}

The gcc compiler on CLEAR generates the following assembly code for these two functions.

1: compute:

2: movq %rdi, %rax

5 of 8

3: movq 8(%rsp), %rsi

4: movq 16(%rsp), %rdx

5: movq 24(%rsp), %rcx

6: movq (%rcx), %rcx

7: leaq (%rdx,%rsi), %rdi

8: addq %rcx, %rdi

9: movq %rdi, (%rax)

10: subq %rdx, %rsi

11: movq %rsi, 8(%rax)

12: subq %rcx, %rdx

13: movq %rdx, 16(%rax)

14: ret

1: caller:

2: subq $104, %rsp

3: movq %rdx, 24(%rsp)

4: leaq 24(%rsp), %rax

5: movq %rdi, (%rsp)

6: movq %rsi, 8(%rsp)

7: movq %rax, 16(%rsp)

8: leaq 32(%rsp), %rdi

9: call compute

10: movq 32(%rsp), %rax

11: addq 40(%rsp), %rax

12: addq 48(%rsp), %rax

13: addq $104, %rsp

14: ret

A. We can see in lines 2-5 of the assembly code for compute that it appears as if four values

are being received from the caller, even though the function has only a single argument.

Describe what these four values are.

B. We can see in line 2 of the assembly code for caller that 104 bytes are allocated in the

stack frame. The first 56 bytes are used as seven fields of 8 bytes each. Describe how

each of these fields is used.

C. How would you describe the general strategy for passing structures as arguments to a

function?

D. How would you describe the general strategy for returning a structure as the return

value from a function?

6 of 8

5. [20 points] Chapter 8 of the textbook, “Exceptional Control Flow”, discusses Unix signals at

length, and Chapter 12, “Concurrent Programming”, introduces POSIX threads. However,

the textbook never discusses how signals should be handled in a multithreaded program.

Consider the following program fragment from a poorly written multithreaded web proxy.

...

FILE *proxy_log_file;

...

static void

SIGUSR1_handler(int sig)

{

(void)sig;

fflush(proxy_log_file);

}

...

int

main(int argc, char **argv)

{

...

proxy_log_file = Fopen("proxy.log", "a");

...

Signal(SIGUSR1, SIGUSR1_handler);

...

}

...

void

process_request(...)

{

...

fprintf(proxy_log_file, "%s\n", log_entry);

...

}

The author of this code defined the SIGUSR1 handler so that network administrators operating

this web proxy would be able to flush any buffered log entries to the log file so that other

applications could read those log entries. To trigger a flush, the network administrator simply

uses the kill command to send a SIGUSR1 signal to the web proxy.

Unfortunately, the approach to handling the SIGUSR1 signal in the above program fragment

is flawed. To understand the flaw, consider the following two facts. First, when a signal is

delivered asynchronously to a multithreaded process, the operating system may preempt an

7 of 8

arbitrary thread to execute the signal handler. (Of course, the operating system will not

preempt a thread that has blocked asynchronous delivery of the signal.) Second, although

the fflush(3), Fopen(), and fprintf(3) functions are thread-safe, they are not asyncsignal-safe.

These functions achieve thread-safety through locking the specified I/O stream.

Describe a concurrency problem that can arise from calling fflush(2) inside a

signal handler of a multithreaded.

The recommended approach to handling a signal in a multithreaded program is to block

the asynchronous delivery of that signal to all threads within the process and create a dedicated

thread that receives the signal synchronously by calling sigwait(2), sigtimedwait(2),

or sigwaitinfo(2). Asynchronous signal delivery can be blocked for an individual thread

using pthread_sigmask(3). Alternatively, a signal can be blocked for all threads using

sigprocmask(2). Modify the above program fragment to use this approach.

8 of 8


版权所有:留学生编程辅导网 2020 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp