fork y read, cómo funciona?

B

Hola a todos, estoy haciendo un programa que dado un sistema virtual de ficheros (ext2) lea primero el superbloque, mire cuántos bloques hay por grupo de bloques y cuántos bloques totales hay, de aquí vea cuántos grupos de bloques hay y para cada bloque lance un hijo que lea el descriptor del grupo. Esta lectura la saco de un archivo .img.

El problema es que una vez calculo el número de grupos, al hacer el fork este me cambia, y no sé si es porque el puntero a fichero se mueve al realizar el fork y me cambia el cálculo que comento.

En fin, cuelgo el código y resalto lo importante a ver si hay suerte...

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "ext2.h"

void main(){
	struct ext2_sb SuperBloque;
	struct ext2_bg Desc_grupos;
	int f_desc,i,num_blocks,f_desc2;

f_desc=open("/fs.img");
    //lectura de todos los datos del superbloque
read(f_desc,&(SuperBloque.s_inodes_count),4);
read(f_desc,&(SuperBloque.s_blocks_count),4);
read(f_desc,&(SuperBloque.s_r_blocks_count),4);
read(f_desc,&(SuperBloque.s_free_blocks_count),4);
read(f_desc,&(SuperBloque.s_free_inodes_count),4);

read(f_desc,&(SuperBloque.s_first_data_block),4);
read(f_desc,&(SuperBloque.s_log_block_size),4);
read(f_desc,&(SuperBloque.s_log_frag_size),4);
read(f_desc,&(SuperBloque.s_blocks_per_group),4);
read(f_desc,&(SuperBloque.s_frags_per_group),4);

read(f_desc,&(SuperBloque.s_inodes_per_group),4);
read(f_desc,&(SuperBloque.s_mtime),4);
read(f_desc,&(SuperBloque.s_wtime),4);
read(f_desc,&(SuperBloque.s_mnt_count),2);
read(f_desc,&(SuperBloque.s_max_mnt_count),2);

read(f_desc,&(SuperBloque.s_magic),2);
read(f_desc,&(SuperBloque.s_state),2);
read(f_desc,&(SuperBloque.s_errors),2);
read(f_desc,&(SuperBloque.s_pad),2);

read(f_desc,&(SuperBloque.s_lastcheck),4);
read(f_desc,&(SuperBloque.s_checkinterval),4);
read(f_desc,&(SuperBloque.s_creator_os),4);
read(f_desc,&(SuperBloque.s_rev_level),4);
read(f_desc,&(SuperBloque.s_reserved),944);

ext2_print_sb(&SuperBloque); //escritura de los datos (librería ext2.h)
num_blocks=SuperBloque.s_blocks_count/SuperBloque.s_blocks_per_group+1; //calculo número de grupos, da 4139

for(i=0;i<num_blocks;i++){

	switch(fork()){
		case -1:
			printf("Error\n"); //nunca se imprime así que por aquí no falla
			return;
			break;
		case 0:
                            //lectura descriptor, aquí la variable num_blocks vale milagrosamente 384864
			read(f_desc1,&(Desc_grupos.bg_block_bitmap),4);
			read(f_desc1,&(Desc_grupos.bg_inode_bitmap),4);
			read(f_desc1,&(Desc_grupos.bg_inode_table),4);
			read(f_desc1,&(Desc_grupos.bg_free_blocks_count),2);
			read(f_desc1,&(Desc_grupos.bg_free_inodes_count),2);
			read(f_desc1,&(Desc_grupos.bg_used_dirs_count),2);
			read(f_desc1,&(Desc_grupos.bg_pad),2);
			read(f_desc1,&(Desc_grupos.bg_reserved),12);
			ext2_print_bg(&Desc_grupos);

			exit(1);
			break;
		default:
			wait();

			break;
	}
}
close(f_desc);
}

Yo supongo que tiene algo que ver con el tema de hacer fork y que el puntero se va moviendo y no lo controlo, ya que si num_blocks le pongo directamente 4139 no me falla, por supuesto.

Gracias por la ayuda!

skv

A qué te refieres con lectura del descriptor? Donde está la linea que inicializa/crea f_desc1? Solo veo declaradas las variables f_desc y f_desc2.

LOc0
prueba esto

Y dime si no te imprime siempre lo mismo el padre y el hijo que es lo que debería pasar ya que la variable num_grupos se asigna ANTES del fork() y no cambia dentro del bucle.

Salu2 ;)

B

Hola!

Gracias por la ayuda, al final el problema no era de mi código... sino de que al montar el sistema de archivos virtual seguía los pasos:

dd if=/dev/loop0 of=fs.img bs=1M count=10
sudo losetup /dev/loop0 fs.img
sudo mke2fs /dev/loop0

Y no especificaba que tenía que ser de tipo ext2, me lo hacía de tipo ext3 y no cuadraba nada (tenía que escribir mke2fs -t ext2 /dev/loop0).

Por si a alguien le interesa, el código final:

int main(int argc, char *argv[]){
	int f_desc,i;
	struct ext2_sb SuperBloque;
	struct ext2_bg BloqueDescriptor;
	int num_grupos;

//Comprobamos que en la entrada haya el archivo
if (argc != 2)
    ERROR("Especifique el archivo que hay que leer.\n");

//Abrimos el archivo
if((f_desc=open(argv[1],O_RDONLY))==-1)
ERROR("Error en la apertura del archivo.\n");

//Situamos el puntero r/w al inicio del Superbloque (saltamos el boot)
if(lseek(f_desc,BLOCK_SIZE,SEEK_SET)==-1)
ERROR("Error de lectura 1:No se ha podido llegar al SB.\n");

//Leemos el primer bloque que coincide con el superbloque
	if(read(f_desc, &SuperBloque, BLOCK_SIZE)<BLOCK_SIZE)
ERROR("Error de lectura 2.\n");

ext2_print_sb(&SuperBloque);

num_grupos=SuperBloque.s_blocks_count/SuperBloque.s_blocks_per_group+1;
printf("%d\n",num_grupos);
for(i=0;i<num_grupos;i++){
	switch(fork()){
		case -1:
			ERROR("Error al crear el hijo\n");
		case 0:
			if(lseek(f_desc,(off_t) 2*BLOCK_SIZE + i*DESCRIPTOR_SIZE,SEEK_SET)==-1)
				ERROR("Error al desplazar el puntero r/w al inicio de cada bloque descriptor.\n");

			if(read(f_desc, &BloqueDescriptor, (size_t) DESCRIPTOR_SIZE)<DESCRIPTOR_SIZE)
				ERROR("Error leyendo los descriptores del grupo.\n");
			printf("----Grupo de bloques %d----\n", i);
			ext2_print_bg(&BloqueDescriptor);
			printf("\n\n");
			exit(0);
		default:
			wait();
			break;
	}
    }
close(f_desc);
return 0;
}

Usuarios habituales