Tagg C

Min guide till Whilenium

I en projektkurs den här perioden ”Operativsystem” har vi skapat ett ganska grundläggande operativsystem vid namn ”Whilenium”, vi har kört det genom Simics med emulering av MIPS. Simics beskrivs så här av Wikipedia:

Simics is a full-system simulator used to run unchanged production binaries of the target hardware at high-performance speeds. Simics was originally developed by the Swedish Institute of Computer Science (SICS), and then spun off to Virtutech for commercial development in 1998.

Vårt operativsystem har i korta drag följande funktioner:

  • Skapa flera processer
  • Köra processerna samtidigt
  • Skicka och ta emot I/O

Däremellan är det väldigt mycket saker varje process ska kunna göra (och inte göra), exempelvis ska processerna kunna avsluta varandra, inte dela minne med varandra etc.

Det har varit en väldigt intressant kurs som byggde på en tidigare väldigt teoretisk kurs med mycket praktiskt arbete. Det som var svårast var nog att förstå kopplingen mellan C och Assembler. Därefter stötte vi på en del problem vad gäller schemaläggningen av processer samt få till systemanropen för att hoppa mellan ”User-space” och ”Kernel-space”

För de som är intresserade kan ni ladda ner källkoden och se (den väldigt korta) dokumentationen här. Ni kan även besöka vårt projekt på Google Code.

Källkoden har en del struktureringsbrister och är inte helt komplett dokumenterad, det hann vi inte med i slutspurten av projektet.


Tack till Jesper Friberg, Oskar Wirén och Daniel Lervik för ett bra arbete!

Enkelt shell skrivet i C

Tänkte snabbt lägga upp koden som vi gjorde i en skoluppgift. Uppgiften gick ut på att skapa en del i ett shell-script, närmare bestämt den delen där kommandon som skrivs i shellet ”pipas”.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
 
#include <sys/types.h>
#include <sys/wait.h>
 
/* The array below will hold the arguments: args[0] is the command. */
static char* args[512];
pid_t pid;
int command_pipe[2];
 
#define READ  0
#define WRITE 1
 
/*
 * Handle commands separatly
 * input: return value from previous command (useful for pipe file descriptor)
 * first: 1 if first command in pipe-sequence (no input from previous pipe)
 * last: 1 if last command in pipe-sequence (no input from previous pipe)
 *
 * EXAMPLE: If you type "ls | grep shell | wc" in your shell:
 *    fd1 = command(0, 1, 0), with args[0] = "ls"
 *    fd2 = command(fd1, 0, 0), with args[0] = "grep" and args[1] = "shell"
 *    fd3 = command(fd2, 0, 1), with args[0] = "wc"
 *
 * So if 'command' returns a file descriptor, the next 'command' has this
 * descriptor as its 'input'.
 */
static int command(int input, int first, int last)
{
	int pipettes[2];
 
	/* Invoke pipe */
	pipe( pipettes );	
	pid = fork();
 
	/*
	 SCHEME:
	 	STDIN --> O --> O --> O --> STDOUT
	*/
 
	if (pid == 0) {
		if (first == 1 && last == 0 && input == 0) {
			// First command
			dup2( pipettes[WRITE], STDOUT_FILENO );
		} else if (first == 0 && last == 0 && input != 0) {
			// Middle command
			dup2(input, STDIN_FILENO);
			dup2(pipettes[WRITE], STDOUT_FILENO);
		} else {
			// Last command
			dup2( input, STDIN_FILENO );
		}
 
		if (execvp( args[0], args) == -1)
			_exit(EXIT_FAILURE); // If child fails
	}
 
	if (input != 0) 
		close(input);
 
	// Nothing more needs to be written
	close(pipettes[WRITE]);
 
	// If it's the last command, nothing more needs to be read
	if (last == 1)
		close(pipettes[READ]);
 
	return pipettes[READ];
}
 
/* Final cleanup, 'wait' for processes to terminate.
 *  n : Number of times 'command' was invoked.
 */
static void cleanup(int n)
{
	int i;
	for (i = 0; i < n; ++i) 
		wait(NULL); 
}
 
static int run(char* cmd, int input, int first, int last);
static char line[1024];
static int n = 0; /* number of calls to 'command' */
 
int main()
{
	printf("SIMPLE SHELL: Type 'exit' or send EOF to exit.\n");
	while (1) {
		/* Print the command prompt */
		printf("$> ");
		fflush(NULL);
 
		/* Read a command line */
		if (!fgets(line, 1024, stdin)) 
			return 0;
 
		int input = 0;
		int first = 1;
 
		char* cmd = line;
		char* next = strchr(cmd, '|'); /* Find first '|' */
 
		while (next != NULL) {
			/* 'next' points to '|' */
			*next = '\0';
			input = run(cmd, input, first, 0);
 
			cmd = next + 1;
			next = strchr(cmd, '|'); /* Find next '|' */
			first = 0;
		}
		input = run(cmd, input, first, 1);
		cleanup(n);
		n = 0;
	}
	return 0;
}
 
static void split(char* cmd);
 
static int run(char* cmd, int input, int first, int last)
{
	split(cmd);
	if (args[0] != NULL) {
		if (strcmp(args[0], "exit") == 0) 
			exit(0);
		n += 1;
		return command(input, first, last);
	}
	return 0;
}
 
static char* skipwhite(char* s)
{
	while (isspace(*s)) ++s;
	return s;
}
 
static void split(char* cmd)
{
	cmd = skipwhite(cmd);
	char* next = strchr(cmd, ' ');
	int i = 0;
 
	while(next != NULL) {
		next[0] = '\0';
		args[i] = cmd;
		++i;
		cmd = skipwhite(next + 1);
		next = strchr(cmd, ' ');
	}
 
	if (cmd[0] != '\0') {
		args[i] = cmd;
		next = strchr(cmd, '\n');
		next[0] = '\0';
		++i; 
	}
 
	args[i] = NULL;
}

Generell köstruktur i C

Som en del av en skoluppgift så har jag tillsammans med min labbpartner konstruerat en generell köstruktur i C som kan användas för att bygga köer.

Ladda ner källkoden

© Copyright 2002 - 2010 Anders Hassis

Byggt på Notes Blog Core