xv6 libro Capítulo 1 Interfaces del sistema operativo

  • El trabajo de un sistema operativo es compartir una computadora entre múltiples programas y proporcionar un conjunto de servicios más útil que el que admite el hardware por sí solo.
  • Un sistema operativo proporciona servicios a los programas de usuario a través de una interfaz .

fork () crea un nuevo proceso, llamado proceso hijo, con exactamente el mismo contenido de memoria que el proceso de llamada, llamado proceso padre. fork () devuelve tanto el padre como el hijo. En el padre, fork () devuelve el PID del hijo; en el niño, fork () devuelve cero.

La llamada al sistema exit () hace que el proceso de llamada deje de ejecutarse y libere recursos como la memoria y los archivos abiertos. exit () toma un argumento entero, convencionalmente 0 para indicar éxito y 1 para indicar fallo.

La llamada al sistema wait () devuelve el PID de un hijo salido (o eliminado) del proceso actual y copia el estado de salida del hijo a la dirección pasada a esperar.

  • Si ninguno de los hijos de la persona que llama ha salido, wait () espera a que uno lo haga.
  • Si la persona que llama no tiene hijos, wait () devuelve inmediatamente -1.
  • Si al padre no le importa el estado de salida de un hijo, puede pasar una dirección 0 para esperar ().
int pid = fork();
if (pid > 0) {
    
    
	printf("parent: child=%d\n", pid);
	pid = wait((int *) 0);
	printf("child %d is done\n", pid);
}
else if (pif == 0) {
    
    
	printf("child: exiting\n");
	exit(0);
}
else {
    
    
	printf("fork error\n");
}

La llamada al sistema exec () reemplaza la memoria del proceso de llamada con una nueva imagen de memoria cargada desde un archivo almacenado en el sistema de archivos. Cuando el exec tiene éxito, no regresa al programa que lo llama; en su lugar, las instrucciones cargadas desde el archivo comienzan a ejecutarse en el punto de entrada declarado en el encabezado ELF.

char *argv[3];
/*
 * most programs ignore the first element of the argument array, which is
 * conventionally the name of the program
 */
argv[0] = "echo"; 
argv[1] = "hello";
argv[2] = 0;
exec("/bin/echo", argv);
printf("exec error\n");

read (fd, buf, n) lee como máximo n bytes del descriptor de archivo fd, los copia en buf y devuelve el número de bytes leídos. Cada descriptor de archivo que hace referencia a un archivo tiene un desplazamiento asociado. read () lee datos del desplazamiento del archivo actual y luego avanza ese desplazamiento por el número de bytes leídos : una lectura posterior devolverá los bytes que siguen a los devueltos por la primera lectura. Cuando no hay más bytes para leer, read () devuelve cero para indicar el final del archivo.

write (fd, buf, n) escribe n bytes desde buf al descriptor de archivo fd y devuelve el número de bytes escritos. Se escriben menos de n bytes solo cuando se produce un error. Al igual que read (), write escribe datos en el desplazamiento del archivo actual y luego avanza ese desplazamiento por el número de bytes escritos: cada escritura comienza donde se quedó la anterior .

char buf[512];
int n;

for ( ; ; ) {
    
    
	n = read(0, buf, sizeof buf);
	if (n == 0) {
    
    
		break;
	}
	if (n < 0) {
    
    
		fprintf(2, "read error\n");
		exit(1);
	}
	if (write(1, buf, n) != n) {
    
    
		fprintf(2, "write error\n");
		exit(1);
	}
}

La llamada al sistema close () libera un descriptor de archivo , lo que lo hace libre para su reutilización en futuras llamadas al sistema open (), pipe () o dup (). Un descriptor de archivo recién asignado es siempre el descriptor no utilizado con el número más bajo del proceso actual.

char *argvc[2];

argv[0] = "cat";
argv[1] = 0;
if (fork() == 0) {
    
    
	close(0);
	
	open("input.txt", O_RDONLY);
	exec("cat", argv);
}

La llamada al sistema dup () duplica un descriptor de archivo existente y devuelve uno nuevo que se refiere al mismo objeto de E / S subyacente.

fd = dup(1);
// Both file descriptors share an offset,
// just as the file descriptors duplicated by fork() do.
write(1, "hello ", 6);
write(fd, "wordl\n", 6);

pipe () crea una nueva tubería y registra los descriptores de archivo de lectura y escritura en la matriz p. Si no hay datos disponibles, una lectura en una tubería espera a que se escriban los datos para que se cierren todos los descriptores de archivo que hacen referencia al extremo de escritura; en el último caso, read devolverá 0, como si se hubiera llegado al final de un archivo de datos.

int p[2];
char *argv[2];

argv[0] = "wc";
argv[1] = 0;

pipe(p);
if (fork() == 0) {
    
    
	close(0);
	// p[0] the read end of the pipe
	dup(p[0]);
	close(p[0]);
	close(p[1]);
	exec("/bin/wc", argv);
}
else {
    
    
	close(p[0]);
	write(p[1], "hello world\n", 12);
	close(p[1]);
}	

La llamada al sistema chdir () puede cambiar el directorio actual del proceso de llamada.

chdir("/a");
chdir("b");
open("c", O_RDONLY);
// both these two fragments open the same file, but the first change the
// process's directory to /a/b; the second neither refers to nor changes
// the process's current directory
open("/a/b/c", O_RDONLY);

mkdir () crea un nuevo directorio

open () con la bandera O_CREATE crea un nuevo archivo de datos

mknod () crea un archivo especial que se refiere a un dispositivo. Asociados con un archivo de dispositivo están los números de dispositivo mayor y menor (los dos argumentos de mknod), que identifican de forma única un dispositivo del kernel. Cuando un proceso abre posteriormente un archivo de dispositivo, el kernel desvía las llamadas al sistema read () y write () a la implementación del dispositivo del kernel en lugar de pasarlas al sistema de archivos.

mkdir("/dir");
fd = open("/dir/file", O_CREATE|O_WRONLY);
close(fd);
mknod("/console", 1, 1);

La llamada al sistema link () crea otro nombre de sistema de archivos que hace referencia al mismo inodo que un archivo existente

open("a", O_CREATE|O_WRONLY);
// reading from or writing to a is the same as reading from or writing to b
link("a", "b");

Unlink () llamada al sistema elimina un nombre del sistema de archivos. El inodo del archivo y el espacio en disco que contiene su contenido solo se liberan cuando el recuento de enlaces del archivo es cero y ningún descriptor de archivo se refiere a él.

unlink("a");

Supongo que te gusta

Origin blog.csdn.net/weixin_41714373/article/details/109722603
Recomendado
Clasificación