download instant at www.easysemester.com
Chapter 2: Using the Operating System
Exercises
- Start with Figure 2.4. Modify it to open two files for reading (the source files) and one for writing (the result file). The solution will need to assume a key field used to sort the two source files and for combining them into a result file:
#include <stdio.h>
#include <fcntl.h>
#define N_LEN 64
int main () {
int inFile1, inFile2, outFile;
char inFileName1[N_LEN], inFileName2, outFileName;
/* Get the file names */
inFileName1 = getFileName(...);
inFile1 = open(inFileName1, O_RDONLY);
inFileName2 = getFileName(...);
inFile2 = open(inFileName2, O_RDONLY);
outFileName = getFileName(...);
outFile = open(outFileName, O_WRONLY);
/* Loop through the input files */
/* Read record from inFile1 (quit reading if encountered an EOF) */
/* Read record from inFile2 (quit reading if encountered an EOF) */
while(anything left in either file) {
/* Write lexigraphically lowest record to outFile
then read another record from the source file
quit reading that file if EOF has been encountered
*/
/* Close the files and exit */
close(inFile1);
close(inFile2);
close(outFile);
}
}
- Start with Figure 2.5. Modify it to open two files for reading (the source files) and one for writing (the result file). The solution will need to assume a key field used to sort the two source files and for combining them into a result file:
/* Exercise 2.7.2, OSAMP3E
* Skeleton solution
* G. Nutt, June 9, 2003
*/
#include <windows.h>
#include <stdio.h>
#define BUFFER_LEN ...
int main(int argc, char *argv[]) {
// Local variables
char buffer[BUFFER_LEN+1];
// CreateFile parameters
DWORD dwShareMode = 0; // share mode
LPSECURITY_ATTRIBUTES lpFileSecurityAttributes = NULL;
// pointer to security attributes
HANDLE hTemplateFile = NULL;
// handle to file with attributes to copy
// ReadFile parameters
HANDLE sourceFileA, SourceFileB; // The two files to be merged
DWORD numberOfBytesRead; // number of bytes read
LPOVERLAPPED lpOverlapped = NULL; // Not used here
// WriteFile parameters
HANDLE sinkFile; // Result file
DWORD numberOfBytesWritten; // # bytes written
// Open the source files
sourceFileA = CreateFile (
"in_test_A",
GENERIC_READ,
dwShareMode,
lpFileSecurityAttributes,
OPEN_ALWAYS,
FILE_ATTRIBUTE_READONLY,
hTemplateFile
);
if(sourceFile == INVALID_HANDLE_VALUE) {
fprintf(stderr, "File open operation failed\n");
ExitProcess(1);
}
// Open the source files
sourceFileB = CreateFile (
"in_test_B",
GENERIC_READ,
dwShareMode,
lpFileSecurityAttributes,
OPEN_ALWAYS,
FILE_ATTRIBUTE_READONLY,
hTemplateFile
);
if(sourceFile == INVALID_HANDLE_VALUE) {
fprintf(stderr, "File open operation failed\n");
ExitProcess(1);
}
// Open the sink file
sinkFile = CreateFile (
"out_test",
GENERIC_WRITE,
dwShareMode,
lpSecurityAttributes,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
hTemplateFile
);
if(sinkFile == INVALID_HANDLE_VALUE) {
fprintf(stderr, "File open operation failed\n");
ExitProcess(1);
}
// Main loop to copy the file
while
(
/* Write lexigraphically lowest record to outFile
* then read another record from the source file
* quit reading that file if EOF has been encountered
*/
}
// Terminating. Close the sink and source files
CloseHandle(sourceFileA);
CloseHandle(sourceFileB);
CloseHandle(sinkFile);
ExitProcess(0);
}
- Here is a solution:
/*
* Exercise 2.7.3, OSAMP3E
* G Nutt, June 9, 2003
*/
#include <stdio.h>
char promptString[] = "nutt shell >";
int main() {
int chPID, thisChPID;
int stat;
printf("Parent: Welcome to Exercise 2.7.3\n");
// Create a process
if((chPID = fork()) == 0) {
// This is the child
printf("Child: Greetings, I am going to sleep ...");
fflush(stdout);
sleep(20);
printf(" now awake after 20 seconds. Bye\n");
}
// Wait for the child to terminate
printf("Parent: Waiting ...\n");
thisChPID = wait(&stat);
printf("Parent: Child terminated\n");
exit(1);
}
- Use the solution for #3. Substitute CreateProcess() for fork(), and WaitForSingleObject() for wait(). Finally, the Win32 sleep() call takes a microseconds (instead of seconds) argument.
- It should require much less time to create a thread than to create a process. The most time-consuming operation in process creation is copying the parent’s address space for the child; this is not done when a thread is created, since it uses the parent’s address space.
- Here is the idea for the solution. You would have to construct some kind handles to make this work.
CreateFile(LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD 0,
LPSECURITY_ATTRIBUTES NULL,
DWORD dwCreationDisposition,
DWORD FILE_ATTRIBUTE_NORMAL,
HANDLE NULL
) {
int flags;
int result;
if(check(dwDesiredAccess) == 0) {
...
}
if(check(dwDesiredAccess) == GENERIC_READ)
flags = O_RDONLY;
if(check(dwDesiredAccess) == GENERIC_WRITE) {
flags = (check(dwDesiredAccess) ==
GENERIC_READ)? O_RDWR: O_WRONLY
}
switch(check(dwCreationDisposition)) {
case CREATE_NEW:
break;
case CREATE_ALWAYS:
case OPEN_ALWAYS:
flags = flags | O_CREAT;
case OPEN_EXISTING:
break;
case TRUNCATE_EXISTING:
flags = flags | O_CREAT;
break;
default:
break;
}
result = open(lpFileName,flags);
if(check(dwCreationDispostion))
truncate_file(result)
return(make_handle(result));
}
7. Any program can be run periodically in a UNIX system, provided that the system has been initialized with the cron process (see cron(8) by executing man cron on a UNIX system). This process is started by the system when it is initialized, and runs continuously (it is asleep most of the time). It keeps an ordered list of events in a file called /usr/lib/crontab. If a program is to be run periodically, then an entry is made in /usr/lib/crontab by a user that has permission to do so, e.g., the system administrator. cron wakes up when it is time for the event on the top of crontab to be executed, then executes the command (e.g., a shell script), adjusts the list, then goes back to sleep.
- The solution to this problem will depend on the nature of the user-level thread package you have available to you. I am relying on the package providing shared variables among the threads spawned by a single process. The solution is then straight-forward, following this schemata:
/* Create a shared buffer (more if you want more overlap) */
/* We need a mutex variable, but the students do not know about
that yet */
char buf;
...
threadHandle[0] = cthread_fork(producer, 0);
threadHandle[1] = cthread_fork(consumer, 0);
/* The producer reads a character from the file, then writes it
* into the buffer
*/
/* The consumer reads a character from the buffer, then writes it
* it to the second file
*/
- Here is a solution:
#include <stdio.h>
#include <fcntl.h>
FILE *lopen(char *, char *);
main()
/* Similar to page 387 of Kelley and Pohl */
{
FILE *in_file, *out_file;
char *IN_FILE_NAME = "in_test";
char *OUT_FILE_NAME = "out_test";
int c;
in_file = lopen(IN_FILE_NAME, "r");
out_file = lopen(OUT_FILE_NAME, "w");
/* Loop through the input file */
while ((c = getc(in_file)) != EOF)
{
putc(c, out_file);
/* Duplicate the newline character */
if (c == '\n') putc('\n', out_file);
};
/* Close files and quit */
fclose(in_file);
fclose(out_file);
}
FILE *lopen(char *name, char *mode)
{ /* See page 390 of Kelley and Pohl */
FILE *fp;
if((fp = fopen(name, mode)) == NULL)
{
printf("Error on opening %s\n", name);
exit(1);
};
return fp;
}
- Here is a solution:
#!/bin/sh
# Must use Bourne shell
# How it works:
# Pipe ps output to wc; extract line count
# The number of processes is 4 less than the line count.
# There are 3 extra processes (ps, wc and the shell)
# executing the script) and we shouldn't count the ps
# header line
#
# If using System V, replace the ps options -ax with -e.
nprocs=`ps -ax | wc -l`
true_nprocs=`expr $nprocs - 4`
echo $true_nprocs "processes at" `date` >log_file
- Here is a solution:
#include <sys/time.h>
#include <math.h>
double getTime(resolution)
int resolution;
{
int i;
double result;
struct timeval now;
if(gettimeofday(&now, 0)) printf("Time call error\n");
return(((double)(now.tv_sec) +
(((double) now.tv_usec)/1000000.0))*
pow(10.0, (double) -resolution));
}
download instant at www.easysemester.com