CS 0449 – Project 4: /dev/cards
Due: Tuesday, April 8, 2014 at 11:59pm
Standard UNIX and Linux systems come with a few special files like /dev/zero, which returns nothing but zeros when it is read, and /dev/random, which returns random bytes. In this project, you will write a device driver to create a new device, /dev/cards which returns a randomly selected playing card. This will simulate a real deck, with each card being drawn only once until all 52 are selected. It will then restart with a fresh deck.
For this project we will need to create three parts: the device driver, the special file /dev/cards, and a test program to convince ourselves it works
The test program will be an implementation of the game of blackjack.
Our device driver will be a character device that will implement a read function (which is the implementation of the read() syscall) and returns appropriate playing cards (each, a 1 byte value from 0 to 51). As we discussed in class, the kernel does not have the full C Standard library available to it and so we need to use a different function to get random numbers. By including <linux/random.h> we can use the function get_random_bytes(), which you can turn into a helper function to get a single byte:
unsigned char get_random_byte(int max) {
unsigned char c;
get_random_bytes(&c, 1);
return c%max;
}
Your device driver needs to keep the deck state as to avoid dealing a card twice before the deck is exhausted. Use an array to track this information. “Shuffle” the cards using random indices obtained from calls to get_random_byte().
Blackjack (also known as 21) is a multiplayer card game, with fairly simple rules. For this assignment, you will be implementing a simplified version where a user can play against the computer who acts as dealer.
Two cards are dealt to each player. The dealer shows one card face up, and the other is face down. The player gets to see both of his or her cards and the total of them is added. Face cards (Kings, Queens, and Jacks) are worth 10 points, Aces are worth 1 or 11 points, and all other cards are worth their face value. The goal of the game is to get as close to 21 (“blackjack”) without going over (called “busting”).
The human player goes first, making his or her decisions based on the single dealer card showing. The player has two choices: Hit or Stand. Hit means to take another card. Stand means that the player wishes no more cards, and ends the turn, allowing for the dealer to play.
The dealer must hit if their card total is less than 17, and must stand if it is 17 or higher.
Whichever player gets closest to 21 without exceeding it, wins.
The dealer:
? + 10
You:
4 + 10 = 14
Would you like to “hit” or “stand”? hit
The dealer:
? + 10
You:
14 + 10 = 24 BUSTED!
You busted. Dealer wins.
For this assignment you need to do the following:
· Write a program that plays Blackjack
· Have the program intelligently determine if an Ace should be interpreted as a 1 or an 11.
· Gets cards to display by reading bytes from the /dev/cards file.
KDIR := /lib/modules/$(shell uname -r)/build
to
KDIR := /u/SysLab/shared/linux-2.6.23.1
make ARCH=i386
scp USERNAME@thot.cs.pitt.edu:/u/SysLab/USERNAME/hello_dev/hello_dev.ko .
insmod hello_dev.ko
cd /sys/class/misc/hello
cat dev
cd /dev/
mknod hello c 10 63
cat /dev/hello
rm /dev/hello
rmmod hello_dev.ko
The code for the example we went through comes from:
Read that while going through the source to get an idea of what the Module is doing. Start with the third section entitled “Hello, World! Using /dev/hello_world” and read up until the author starts describing udev rules; we are not using udev under QEMU.
When you have an idea of what is going on, make a new directory under your /u/SysLab/USERNAME directory called card_driver:
mkdir card_driver
Copy and rename the hello_dev.c from the example, and copy over the Makefile. Edit the Makefile to build your new file. Change all the references of “hello” to “card_driver”.
To build any changes you have made, on thot in your card_driver directory, simply:
make ARCH=i386
If you want to force a rebuild of everything you may want to remove the object files first:
rm *.o
From QEMU, you will need to download the driver that you just built. Use scp to download the driver to a home directory (/root/ if root):
scp USERNAME@thot.cs.pitt.edu:/u/SysLab/USERNAME/card_driver/card_driver.ko .
As root (either by logging in or via su):
insmod card_driver.ko
Like in the example, we’ll need to determine the MAJOR and MINOR numbers for this particular driver.
cd /sys/class/misc/card_driver
cat dev
and use those numbers to make the /dev/cards file:
cd /dev
mknod cards c MAJOR MINOR
As root (either by logging in or via su):
rmmod card_driver.ko
Then you can remove the /dev/cards file:
rm /dev/cards
Since thot is a 64-bit machine and QEMU emulates a 32-bit machine, we should build with the -m32 flag:
gcc –m32 –o blackjack blackjack.c -static
We cannot run our blackjack program on thot.cs.pitt.edu because its kernel does not have the device driver loaded. However, we can test the program under QEMU once we have installed the new driver. We first need to download blackjack using scp as we did for the driver. However, we can just run it from our home directory without any installation necessary.
One of the major contributions the university provides for the AFS filesystem is nightly backups. However, the /u/SysLab/ partition is not part of AFS space. Thus, any files you modify under your personal directory in /u/SysLab/ are not backed up. If there is a catastrophic disk failure, all of your work will be irrecoverably lost. As such, it is my recommendation that you:
Backup all the files you change under /u/SysLab to your ~/private/ directory frequently!
Loss of work not backed up is not grounds for an extension. You have been warned.
You need to submit:
Make a tar.gz file named USERNAME-project4.tar.gz
Copy it to ~jrmst106/submit/449 by the deadline for credit.