CSCI 4210操作系统设计

码海寻云使
• 阅读 273

CSCI 4210 — Operating Systems
Homework 2 (document version 1.0)
Process Management and Synchronization
• This homework is due in Submitty by 11:59PM EST on Thursday, February 17, 2022
• You can use at most three late days on this assignment
• This homework is to be done individually, so do not share your code with anyone else
• You must use C for this assignment, and all submitted code must successfully compile
via gcc with no warning messages when the -Wall (i.e., warn all) compiler option is used; we
will also use -Werror, which will treat all warnings as critical errors
• All submitted code must successfully compile and run on Submitty, which uses Ubuntu
v20.04.3 LTS and gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
Hints and reminders
To succeed in this course, do not rely on program output to show whether your code is correct.
Consistently allocate exactly the number of bytes you need regardless of whether you use static or
dynamic memory allocation. Further, deallocate dynamically allocated memory via free() at the
earliest possible point in your code. And as covered in initial class videos, make use of valgrind
to check for errors with dynamic memory allocation and use. Also close any open file descriptors
or FILE pointers as soon as you are done using them.
Another key to success in this course is to always read (and re-read!) the corresponding man pages
for library functions, system calls, etc.
Homework specifications
In this second homework, you will use C to implement a multi-process solution to the classic knight’s
tour problem, i.e. can a knight make valid moves to cover all squares exactly once on a given board?
Sonny plays the knight in our assignment.
Goal
The fundamental goal of this homework is to use fork() and waitpid() to achieve a fully synchronized
parallel solution to the knight’s tour problem.
In brief, your program must determine whether a valid solution is possible for the knight’s tour
problem on an m×n board, and if so, how many solutions exist. To accomplish this, your program
uses a brute force approach and simulates all valid moves. For each board configuration, when
multiple moves are detected, each possible move is assigned to a new child process, thereby
forming a process tree of possible moves.
Note that a new child process is created only if multiple moves are possible at that given
point of the simulation. And remember that when you call fork(), the state of the parent process
is copied to the child process.
To communicate between processes, the top-level parent process creates a single pipe that all child
processes will use to report when a knight’s tour is detected. In other words, each child process
will share a unidirectional communication channel back to the top-level parent process.
Further, each child process will communicate with its immediate parent process by reporting the
maximum coverage achieved through to that point of the tree. For each leaf node, this will simply
be the number of squares covered. For each intermediate node, this will be the maximum of values
returned by its child nodes, i.e., the maximum coverage achieved.
Valid moves
A valid move constitutes relocating Sonny the knight two squares in direction D and then one
square 90◦
from D (in either direction), where D is up, down, right, or left.
Key to this problem is the further restriction that Sonny may not land on a square more than once
in his tour. Also note that Sonny starts and finishes on different squares; we are not looking for a
cycle.
When a dead end is encountered (i.e., no more moves can be made), the leaf node process reports
the number of squares covered, including in that count the start and end squares of the tour.
For consistency, row 0 and column 0 identify the upper-left corner of the board. Sonny starts at
the square identified by row r and column c, which are given as command-line arguments.
If a dead end is encountered or a fully covered board is achieved, the leaf node process reports the
number of squares covered as its exit status. Before terminating, if a fully covered board is detected
(i.e., the last move of a knight’s tour has been made), the child process writes to the pipe to notify
the top-level parent process.
Each intermediate node of the tree must wait until all child processes have reported a value. At
that point, the intermediate node returns (to its parent) the maximum of these values (i.e., the
best possible solution below that point) as its exit status.
Once all child processes in the process tree have terminated, the top-level node reports the number
of squares covered, which is equal to product mn if a full knight’s tour is possible. And if a full
knight’s tour is possible, the number of tours found is also reported.
2
Dynamic Memory Allocation
You must use calloc() to dynamically allocate memory for the m × n board. More specifically,
use calloc() to allocate an array of m pointers, then for each of these pointers, use calloc() to
allocate an array of size n.
Of course, you must also use free() and have no memory leaks through all running (and terminating)
processes.
Do not use malloc() or realloc(). Be sure your program has no memory leaks.
Command-line arguments
There are four required command-line arguments.
First, integers m and n together specify the size of the board as m × n, where m is the number
of rows and n is the number of columns. Rows are numbered 0 . . .(m − 1) and columns are
numbered 0 . . .(n − 1).
The next pair of command-line arguments, r and c, indicate the starting square on which Sonny
starts his attempted tour.
Validate inputs m and n to be sure both are integers greater than 2, then validate inputs r and c
accordingly. If invalid, display the following error message to stderr and return EXIT_FAILURE:
ERROR: Invalid argument(s)
USAGE: hw2.out <m> <n> <r> <c>
3
Program Execution
As an example, you could execute your program and have it work on a 3 × 3 board as follows:
bash$ ./hw2.out 3 3 0 0
This will generate the process tree shown below starting with process P1, with <S> indicating the
current position of Sonny and <?> indicating multiple possible moves. The numbers in this diagram

show the order in which Sonny visits each square.
P1:<S>
<?>
<?>

/ \
fork() / \ fork()
/ \
+---+---+---+ +---+---+---+
P2: | 1 | 6 | 3 | P3: | 1 | 4 | 7 |
+---+---+---+ +---+---+---+
| 4 | |<S>| | 6 | | 2 |
+---+---+---+ +---+---+---+
| 7 | 2 | 5 | | 3 |<S>| 5 |
+---+---+---+ +---+---+---+
Note that the center square is not visited at all in this example. Also note that both of these child
processes return 8 as their exit status, which represents the number of squares visited.
To ensure a deterministic order of process creation, if Sonny is in row a and column b, start looking
for moves at row (a-2) and column (b-1), checking for moves counter-clockwise from there.
Try writing out the tree by hand using the 3 × 4 board below. Remember that child processes are

created only when multiple moves are possible from a given board configuration.
P1:<S>

/ \
fork() / \ fork()
/ \
etc. etc.
4
Required output and the “no parallel” mode
When you execute your program, you must display a line of output each time you detect multiple
possible moves, each time you reach a dead end, and each time you notify the top-level parent
process of a full tour via the pipe. Note that a full tour is not considered a dead end.
Below is example output that shows the required output format. In the example, process (PID)
1 is the top-level parent process, with processes 2 and 3 being child processes of process 1. Use
getpid() to display actual process IDs.
bash$ ./a.out 3 3 0 0
PID 1: Solving Sonny's knight's tour problem for a 3x3 board
PID 1: Sonny starts at row 0 and column 0 (move #1)
PID 1: 2 possible moves after move #1; creating 2 child processes...
PID 2: Dead end at move #8
PID 3: Dead end at move #8
PID 1: Search complete; best solution(s) visited 8 squares out of 9
If a full knight’s tour is found, use the output format below.
bash$ ./a.out 3 4 0 0
PID 1: Solving Sonny's knight's tour problem for a 3x4 board
PID 1: Sonny starts at row 0 and column 0 (move #1)
...
PID 5: Sonny found a full knight's tour; notifying top-level parent
...
PID 1: Search complete; found 2 possible paths to achieving a full knight's tour
Match the above output format exactly as shown above, though note that the PID values will
vary. Further, interleaving of the output lines is expected, though the first few lines and the last
line must be first and last, respectively.
Running in “no parallel” mode
To simplify the problem and help you test, you are also required to add support for an optional
NO_PARALLEL flag that may be defined at compile time (see below). If defined, your program uses
a blocking waitpid() call immediately after calling fork(); this will ensure that you do not run
child processes in parallel, which will therefore provide deterministic output that can more easily
be matched on Submitty.
To compile this code in NO_PARALLEL mode, use the -D flag as follows:
bash$ gcc -Wall -Werror -D NO_PARALLEL hw2.c
NOTE: This problem grows extremely quickly, so be careful in your attempts to run
your program on boards larger than 4 × 4.
5
Error handling
If improper command-line arguments are given, report an error message to stderr and abort further
program execution. In general, if an error is encountered, display a meaningful error message
on stderr by using either perror() or fprintf(), then aborting further program execution. Only
use perror() if the given library or system call sets the global errno variable.
Error messages must be one line only and use the following format:
ERROR: <error-text-here>
If a child process encounters an error, return EXIT_FAILURE. In general, a parent process should
terminate and return EXIT_FAILURE if one of its child processes returns EXIT_FAILURE.
Submission Instructions
To submit your assignment (and also perform final testing of your code), please use Submitty.
Note that this assignment will be available on Submitty a minimum of three days before the due
date. Please do not ask when Submitty will be available, as you should first perform adequate
testing on your own Ubuntu platform.
That said, to make sure that your program does execute properly everywhere, including Submitty,
use the techniques below.
First, make use of the DEBUG_MODE technique to make sure that Submitty does not execute any
debugging code. Here is an example:

ifdef DEBUG_MODE

printf( "the value of q is %d\n", q );
printf( "here12\n" );
printf( "why is my program crashing here?!\n" );
printf( "aaaaaaaaaaaaagggggggghhhh!\n" );

endif

And to compile this code in “debug” mode, use the -D flag as follows:
bash$ gcc -Wall -Werror -g -D DEBUG_MODE hw2.c
Second, output to standard output (stdout) is buffered. To disable buffered output for grading on
Submitty, use setvbuf() as follows:
setvbuf( stdout, NULL, _IONBF, 0 );
You would not generally do this in practice, as this can substantially slow down your program, but
to ensure good results on Submitty, this is a good technique to use.
WX:codehelp

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
4年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
4年前
Android蓝牙连接汽车OBD设备
//设备连接public class BluetoothConnect implements Runnable {    private static final UUID CONNECT_UUID  UUID.fromString("0000110100001000800000805F9B34FB");
Wesley13 Wesley13
4年前
00_设计模式之语言选择
设计模式之语言选择设计模式简介背景设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式(Designpattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这