the real and its double
Download
Report
Transcript the real and its double
Background Survey Answers
Operating Systems
CS 550
Spring 2016
Kenneth Chiu
Q5: Let’s say you have process A writing a
number to a shared memory region. Process B
reads the number from the shared memory
region. Both processes are started at the same
time. How do you make sure that Process B
doesn’t read the number until Process A has
finished writing the number?
A: This is a traditional producer-consumer
problem with a queue size of 1.
Q6: Write a C or C++ program to create a file named “data” containing exactly
1024 bytes with each byte having the value 0xff.
A: Many people had trouble with this. Mainly just looking for the fact that you
know there’s a key difference between ASCII and binary output, and just
some ideas about how to do it. (In the real world, if you just have some slight
idea, then you can quickly Google it. If you have no idea, then you don’t even
know what to Google for in some cases.)
– #include <stdio.h>
#include <assert.h>
int main() {
int rv;
FILE *f = fopen(“data”, “w”); assert(f != 0);
char b = 0xff;
for (int i = 0; i < 1024; i++) {
rv = fwrite(&b, 1, 1, f);
assert(rv == 1);
}
rv = fclose(f); assert(rv == 0);
return 0;
}
Q7: Finish this function fragment to allocate two arrays using a single malloc()
call:
– void func(int n1, int n2) {
// Allocate enough memory for both arrays.
char *tmp = malloc(...);
// Should point to beginning of n1 ints.
int *int_array = ...;
// Should point to beginning of n2 doubles.
double *double_array = ...;
for (int i = 0; i < n1; i++)
int_array[i] = i; // Initialize the array of ints.
for (int i = 0; i < n2; i++)
double_array[i] = i; // Initialize the array of doubles.
A:
– void func(int n1, int n2) {
char *tmp = malloc(n1*sizeof(int) + n2*sizeof(double));
int *int_array = (int *) tmp;
double *double_array = (double *) (tmp + n1*sizeof(int));
for (int i = 0; i < n1; i++)
int_array[i] = i;
for (int i = 0; i < n2; i++)
double_array[i] = i;
Q8: Write code to test at run-time whether the
machine is little-endian or big-endian? If you
were required to determine the same
information at compile-time, how would you do
it?
– int i = 1;
if (*(char *) &i == 1) {
printf(“little-endian\n”);
} else {
printf(“big-endian\n”);
}
– At compile time, use an #ifdef of some type.
Q9: Let’s say that you have 1000 JPEG files in a
folder and its subfolders. Each file begins with
the letters PIC. You wish to rename them all so
that they begin with IMG instead. How would
you do this?
A: Correct answers: (1) “I would write a script in
XYZ.” (2) “I would use the rename command.”
(3) “I would create a sequence of commands
in ABC.” Some people talked about the
algorithm, or write a program in C, etc.
Q10. How do you debug a memory leak?
A: What’s hard about it?
– Use valgrind, Purify, etc.
– If you can’t, you might be able to watch it in ‘top’.
– To fix, if you can’t use valgrind, then you it
becomes very difficult.
Q11. What causes a segfault? How do you
debug it?
– A segfault is caused by access to “unmapped”
memory. It doesn’t exist, in other words.
– Typically, it means you somehow got garbage
values into a pointer.
– valgrind is the best tool. Otherwise, gdb can be
used.
Q12: Is this program correct? What do you think it
will print out when you compile and run it? Explain
why.
– #include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *s = (char *) malloc(10);
strcpy(s, “hello”);
free(s);
printf(“%s\n”, s);
}
A: Some people thought it would give segfault.
Q13: Assume that you have a file named foo in the current directory. The first
four bytes contain an integer in binary using two’s complement (in native byte
order). Let this integer have the value N. The next N bytes then contain a
string. The string is not terminated with a 0 (null) byte. Write a program in any
language and OS that will read in the string and print it to the console
(standard output).
A: First read the length, then read the rest.
– #include <unistd.h>
#include <stdlib.h>
#include <assert.h>
int main() {
int rv;
int fd = open(“foo”, O_RDONLY); assert(fd >= 0);
unsigned int n;
rv = read(fd, &n, 4); assert(rv == 4);
char *str = malloc(n + 1);
str[n] = ‘\0’;
rv = read(fd, str, n); assert(rv == n);
rv = close(fd); assert(rv == 0);
printf(“%s\n”, str);
}
Q: Sketch a program that will be CPU-bound.
A: A program that solves the TSP.
Q: Sketch a program that will be IO-bound.
A: Databases are usually I/O bound.
Q14: What does a linker do?
A: It resolves symbol references in object code
to addresses and/or numbers, and combines the
files into one file, usually an executable.
Q15: Why is a shared library called a shared
library?
A: Because it’s memory image can be shared by
multiple processes.
Q16: Which is harder to debug, a deadlock or a
race condition?
A: Deadlocks are relatively easy. Attach to it with
gdb. Check where all the threads are. Next step
is harder, but then you need to backtrack to
figure out how it got into this state. Usually, you
can add a bunch of print statements to trace it.
Race conditions can be very hard to debug.
That’s because two given concurrent executions
can have many different interleavings.