Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Programando en C en Linux.

Estas en el tema de Programando en C en Linux. en el foro de C/C++ en Foros del Web. Hola a todos, aquí vengo con una nueva duda. Hace poco he comenzado a programar en C bajo entorno Linux haciendo usa de los comandos ...
  #1 (permalink)  
Antiguo 24/10/2006, 13:37
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
Programando en C en Linux.

Hola a todos, aquí vengo con una nueva duda.
Hace poco he comenzado a programar en C bajo entorno Linux haciendo usa de los comandos de dicho sistema operativo. Mi pregunta es la siguiente. Quiero comprobar cada x segundos si determinado fichero ha sido modificado. Aún no tengo claro como hacerlo, pero he investigado y creo que mediante las funciones exec o system es posible, y creo que la función que puede resolver mi problema es stat o fstat. Alguién puede orientarme un poco sobre mi problemilla??
P.D. Lo de la comprobación cada x segundos creo que se hace con la función sleep(x)
Muchas gracias, un saludo.
  #2 (permalink)  
Antiguo 24/10/2006, 14:52
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
No entendi muy bien tu duda, pero quieres hacer un programa que haga es? o quieres que un program ya hecho te ayude a hacer eso.

En el segundo caso, creo yo(no estoy 100% seguro) que el make te resuelve ese tipo de cosas, en caso de compilacion y procesos de ese estilo.

Si no, pues si debes de usa run programa(comando) como los que mencionaste.

Saludos
  #3 (permalink)  
Antiguo 24/10/2006, 15:00
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
Trataré de explicarme mejor. La duda que tenga es de una parte de un programa algo más grande. Para programar uso Anjuta, compilador para Linux. Lo que quiero es hacer yo el programa, no uno ya hecho, programando en C utilizando las funciones system y exec que permiten el uso de comandos de linux.
Resumiendo, leí algo de que con fstat se podía hacer lo que quiero; comprobar cada 10 segundos si un fichero ha sido modificado o no, y en caso de haber sido modificado indicar cuando fué modificado.
Espero haberme expresado algo mejor, gracias por tu ayuda Instru.
Saludos.
  #4 (permalink)  
Antiguo 24/10/2006, 15:27
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
A, pues en ese caso necesitas hacer una especia de demonio. La verdad yo no se hacerlos. Pero posiblemente MaxExtreme te pueda ayudar mas adelante.

Saludos

PD: Anjuta no e sun compilador, es solo uno de los tantos IDEs para GNU/GCC, make, autoconf, etc etc, etc

Saludos
  #5 (permalink)  
Antiguo 24/10/2006, 15:42
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
Gracias por la aclaración. Y a lo de hacer una especie de demonio quizás te quieras referir a crear nuevos procesos hijos a partir de procesos padres con la sentencia fork(). De todas formas esperaré a ver si el amigo MaxExtreme me puede ofrecer alguna pista(ya me ofreció su ayuda en un tema anterior que planteé). De todas formas seguiré investigando.
Muchas gracias.
  #6 (permalink)  
Antiguo 24/10/2006, 16:15
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por yournightmare86 Ver Mensaje
Trataré de explicarme mejor. La duda que tenga es de una parte de un programa algo más grande. Para programar uso Anjuta, compilador para Linux. Lo que quiero es hacer yo el programa, no uno ya hecho, programando en C utilizando las funciones system y exec que permiten el uso de comandos de linux.
Resumiendo, leí algo de que con fstat se podía hacer lo que quiero; comprobar cada 10 segundos si un fichero ha sido modificado o no, y en caso de haber sido modificado indicar cuando fué modificado.
Espero haberme expresado algo mejor, gracias por tu ayuda Instru.
Saludos.
Así rápidamente te respondo (es hora de dormir aquí :):

1. Una cosa: Anjuta no es un compilador, es el IDE. El compilador es gcc (normalmente).
2. Para comprobar algo cada 10 segundos, sí, puedes hacer un bucle while(seguir) { sleep(10000); ... } aunque también tienes otras opciones como usar timers del sistema operativo, que llamarán a una función que quieras cada X tiempo que desees.
3. Sobre fstat, ¿qué duda tienes?

Aquí te dejo un ejemplo extra-rápido de cómo podrías hacerlo

Código:
struct stat estado;
time_t ultimo;
int fd = open("fichero", O_RDONLY);
while(...) {
     fstat(fd, &estado);
     if(estado.st_mtime != ultimo) {
         ultimo = estado.st_mtime;
         printf("%s - Archivo modificado\n", asctime(estado.st_mtime));
     }
     sleep(10);
}
close(fd);
No sé si estará bien. Ten en cuenta que tendrás que poner alguna clase de condición en los "..." para poder parar el programa.
  #7 (permalink)  
Antiguo 25/10/2006, 05:50
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
La duda no era tan duda,sino más bien era la necesidad de ver un ejemplo... ya que no encontré ningún ejemplo claro... Muchas gracias por contestar. Creo que con esto será suficiente. Gracias.
Saludos.
  #8 (permalink)  
Antiguo 25/10/2006, 06:33
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
De nada :)
  #9 (permalink)  
Antiguo 25/10/2006, 14:34
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
A pesar de parecer pesado planteo una úlima duda.
Si quiero pasarle como parámetro el fichero sobre el cual debo hacer la comprobación, cómo lo hago? Ej: comprobar /home/javi/fichero
Bastaría con poner la ruta del fichero?
Saludos.
  #10 (permalink)  
Antiguo 25/10/2006, 16:20
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
¿Te refieres a hacerlo como...

$ modified file.txt

Si es así:

int main(int argc, char * argv[]) {
...
if(argc != 2) {
printf("Sintaxis: %s fichero-a-comprobar\n", argv[0]);
return 1;
}
...
fopen(argv[1],...
  #11 (permalink)  
Antiguo 26/10/2006, 03:24
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
Eso era, gracias de nuevo no lo tenía claro. Pasar de programar en windows con ficheros lisas enlazadas etc. a pasar a linux con nuevos comandos y realizar tareas del sistema es algo complicado jeje.
Saludos.
  #12 (permalink)  
Antiguo 26/10/2006, 03:38
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Ese es el main standard, funciona en cualquier S.O. ya que de eso se encarga la CRT.
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #13 (permalink)  
Antiguo 26/10/2006, 05:32
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
Mi código finalmente es éste.
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
int main (int argc, char * argv[])
{
struct stat estado;
time_t ultimo;
int fd,i;
printf("\n Fichero a comprobar %s", argv[1]);
for(i=0;i<3;i++)
{
fd = open(argv[1],O_RDONLY);
fstat(fd,&estado);
if(estado.st_mtime != ultimo)
{
ultimo = estado.st_mtime;
printf("\n- El archivo %s ha sido modificado",argv[1]);
}
else
{
printf("\n- El archivo %s no ha sido modificado",argv[1]);
}
sleep(10);
i=0;
close(fd);
}
return 0;
}
He incluido ese bucle for ya que la comprobación del archivo en principio no tiene condición de salida, por tanto el programa se ejecuta hasta que el usuario lo pare. La única pega es que la primera vez, me muestra por pantalla "El fichero x ha sido modificado", cuando en realidad no le he tocado... Las demás veces funciona perfectamente.
  #14 (permalink)  
Antiguo 26/10/2006, 05:40
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Una solucion simple seria esta:

Código:
  fd = open(argv[1], O_RDONLY);
  fstat(fd, &estado);
  ultimo = estado.st_mtime;
  close(fd);
Solo hay que inicializar la variable al comienzo, justo antes del bucle, sino ultimo tiene un valor indefinido.
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #15 (permalink)  
Antiguo 26/10/2006, 05:54
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Unos minimos retoques y funciona en Windows, compilado con VC++ que se quejaba sobre tu problema, d:\src\posix.cpp(27) : warning C4700: local variable 'ultimo' used without havin
g been initialized

Código:
#include <windows.h>
extern "C" open(char*, unsigned long);
extern "C" close(int);

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>

int main (int argc, char * argv[])
{
	struct stat estado;
	time_t ultimo;
	int fd, i;
	printf("\n Fichero a comprobar %s", argv[1]);

	fd = open(argv[1], O_RDONLY);
	fstat(fd, &estado);
	ultimo = estado.st_mtime;
	close(fd);

	for(i=0;i<3;i++)
	{
		fd = open(argv[1],O_RDONLY);
		fstat(fd,&estado);
		if(estado.st_mtime != ultimo)
		{
			ultimo = estado.st_mtime;
			printf("\n- El archivo %s ha sido modificado", argv[1]);
		}
		else
		{
			printf("\n- El archivo %s no ha sido modificado", argv[1]);
		}
		Sleep(10 * 1000);
		i = 0;
		close(fd);
	}
	return 0;
}
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #16 (permalink)  
Antiguo 26/10/2006, 05:54
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Hum, no estoy seguro, pero creo que no hace falta que re-abras el archivo cada vez que quieras comprobar su estado. Es decir:

open() puede ir al principio, una vez, antes de entrar en el bucle.
close() puede ir al final, una vez, después de terminar el bucle.

Por otra parte, DEBES comprobar el número de argumentos. Si ejecutases el programa como

$ modified

sin nada más, estarías accediendo a argv[1] que no existe.

Por último, si quieres un bucle infinito, no lo hagas con un for y poniendo i a 0 cada pasada. Tienes dos opciones mejores:

while(1) { ... }
for(;;) { ... }

Además, si usas un bucle infinito, sería bueno que capturases la signal TERM para que cuando te llegue salgas del bucle y llegues a cerrar el archivo que tienes abierto. Si no, el programa deja cosas sueltas; aunque el sistema operativo se encargará de solucionarlas, pero...
  #17 (permalink)  
Antiguo 26/10/2006, 06:06
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Cita:
Iniciado por MaxExtreme Ver Mensaje
Hum, no estoy seguro, pero creo que no hace falta que re-abras el archivo cada vez que quieras comprobar su estado.
Eso funcionaria si lo abriera con permisos para compartir Sino ni dios lo va a poder modificar, supongo que en Linux sera igual.

Cita:
Iniciado por MaxExtreme Ver Mensaje
while(1) { ... }
for(;;) { ... }
Depende en que compilador, VC++ es lo suficientemente bueno como para no hacerlo, si usas while(1) comprueba todas las veces que 1 sea true, asi que siempre es mejor for (;;).
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #18 (permalink)  
Antiguo 26/10/2006, 06:20
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por Eternal Idol Ver Mensaje
Eso funcionaria si lo abriera con permisos para compartir Sino ni dios lo va a poder modificar, supongo que en Linux sera igual.
Ciertamente, hay que asignar la bandera F_RDLCK para que sea compartido. Despiste tonto. Deberían agregar a POSIX un método de apertura que no sea ni Read ni Write, sólo para consultar estado.

Cita:
Depende en que compilador, VC++ es lo suficientemente bueno como para no hacerlo, si usas while(1) comprueba todas las veces que 1 sea true, asi que siempre es mejor for (;;).
Si un compilador hace tal comprobación en cada paso, podemos ir mandándole al Hall of Shame.
  #19 (permalink)  
Antiguo 26/10/2006, 07:51
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años
Puntos: 9
Una vez más gracias, tomo nota de lo del for(;;) yo había intentado for() xD.
  #20 (permalink)  
Antiguo 26/10/2006, 08:42
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Cita:
Iniciado por MaxExtreme Ver Mensaje
Si un compilador hace tal comprobación en cada paso, podemos ir mandándole al Hall of Shame.
Je, en realidad esta haciendo EXACTAMENTE lo que el codigo pide

Código:
#include <stdio.h>

void main()
{
	while(1)
	{
		printf("shame on you compiler!\r\n");
	};
}
cl shame.cpp (en negrita marcada la operacion redundante):
Código:
_main:
  00000000: 55                 push        ebp
  00000001: 8B EC              mov         ebp,esp
  00000003: B8 01 00 00 00     mov         eax,1
  00000008: 85 C0              test        eax,eax
  0000000A: 74 0F              je          0000001B
  0000000C: 68 00 00 00 00     push        offset $SG611
  00000011: E8 00 00 00 00     call        _printf
  00000016: 83 C4 04           add         esp,4
  00000019: EB E8              jmp         00000003
  0000001B: 5D                 pop         ebp
  0000001C: C3                 ret
cl shame.cpp /O1 (esta es la opcion por defecto en REALEASE desde el IDE):
Código:
_main:
  00000000: 68 00 00 00 00     push        offset ??_C@_0BJ@GJEKHHMF@shame?5on?5
you?5compiler?$CB?$AN?6?$AA@
  00000005: E8 00 00 00 00     call        _printf
  0000000A: 59                 pop         ecx
  0000000B: EB F3              jmp         _main
Ni siquiera contempla la posibilidad de retornar jamas

Código:
#include <stdio.h>

void main()
{
	for (;;)
	{
		printf("shame on you compiler!\r\n");
	};
}

cl shame.cpp:
Código:
_main:
  00000000: 55                 push        ebp
  00000001: 8B EC              mov         ebp,esp
  00000003: 68 00 00 00 00     push        offset $SG611
  00000008: E8 00 00 00 00     call        _printf
  0000000D: 83 C4 04           add         esp,4
  00000010: EB F1              jmp         00000003
cl shame.cpp /O1
Código:
_main:
  00000000: 68 00 00 00 00     push        offset ??_C@_0BJ@GJEKHHMF@shame?5on?5
you?5compiler?$CB?$AN?6?$AA@
  00000005: E8 00 00 00 00     call        _printf
  0000000A: 59                 pop         ecx
  0000000B: EB F3              jmp         _main
Como vemos el resultado final con optimizacion es exactamente el mismo
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 12:45.