TODOPIC
Lenguajes de programación para PC => C, C#, C++ => Mensaje iniciado por: migsantiago en 19 de Abril de 2008, 16:01:45
-
Hola
Estoy estudiando cómo matar procesos hijos y cuando mueren cómo leer un valor desde el proceso padre. Apenas estoy conociendo las funciones exit y wait y la de wait me tiene muy confundido.
El programa que no me gusta cómo funciona es el siguiente...
/* Este programa hace que un hijo haga una suma de numeros pasados por parametro para
que posteriormente, cuando el hijo muera, devuelva al programa padre la suma de dichos numeros */
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
main(int argc,char *argv[])
{
int num,estado;
switch(fork())
{
case 0:
{
/* El hijo calcula la operación y lo devuelve con el exit() */
printf("HIJO %d %d \n",atoi(argv[1]),atoi(argv[2]));
num=atoi(argv[1]) + atoi(argv[2]);
printf("HIJO %d %d\n",num,(char)num);
exit(num);
}
default:
{
/* El padre recibe con el wait lo devuelto por el hijo en el exit y lo imprime por pantalla */
wait(&estado);
printf("PADRE %0x %d\n",&estado,estado);
printf("\nPADRE la suma de los hijos es: %d, %d\n",estado/256,estado);
printf("PADRE %lu\n",sizeof(estado));
}
}
}
Ejecutando el programa en el bash de linux pongo:
$ ./programa 10 10
Le entrego 10 y 10 y debe hacer la suma de 20 y el padre reconocerla como 20, pero los resultados en pantalla son los siguientes...
HIJO 10 10
HIJO 20 20
PADRE bfbe9538 5120
PADRE la suma de los hijos es: 20, 5120
PADRE 4
Supuestamente exit entrega los 8 bits menos significativos del int llamado num. Luego wait los recibe y lo guarda en estado, pero he aquí el dilema, no recibe 20, recibe la cantidad de 5120, que es como si multiplicara 20 x 256. Por eso es que unas líneas después corrijo el número dividiéndolo entre 256.
La pregunta... ¿por qué se multiplica el número por 256 (o se rota 8 bits a la izquierda) al moverlo de un hijo a un padre? :(
-
Con estos cambios funciona correctamente:
/* Este programa hace que un hijo haga una suma de numeros pasados por parametro para
que posteriormente, cuando el hijo muera, devuelva al programa padre la suma de dichos numeros */
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
main(int argc,char *argv[])
{
int num,estado,error;
switch(fork())
{
case 0:
{
/* El hijo calcula la operación y lo devuelve con el exit() */
printf("HIJO %d %d \n",atoi(argv[1]),atoi(argv[2]));
num=atoi(argv[1]) + atoi(argv[2]);
printf("HIJO %d %d\n",num,(char)num);
exit(num);
}
default:
{
/* El padre recibe con el wait lo devuelto por el hijo en el exit y lo imprime por pantalla */
wait(&estado);
error=WEXITSTATUS(estado);
printf("PADRE %0x %d\n",&estado,estado);
printf("\nPADRE la suma de los hijos es: %d, %d\n",estado/256,error);
printf("PADRE %lu\n",sizeof(estado));
}
}
}
Tienes que usar WEXITSTATUS para obtener el código de error que devuelve el proceso al salir.
Saludos,
Miguel Angel.
-
Muchas gracias Miguel Angel, eso que me acabas de enseñar ni mi maestro supo explicarlo :D
El programa ya funcionando es:
/* Este programa hace que un hijo haga una suma de numeros pasados por parametro para
que posteriormente, cuando el hijo muera, devuelva al programa padre la suma de dichos numeros */
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
main(int argc,char *argv[])
{
int num,estado;
int error;
switch(fork())
{
case 0:
{
/* El hijo calcula la operación y lo devuelve con el exit() */
printf("HIJO %d %d \n",atoi(argv[1]),atoi(argv[2]));
num=atoi(argv[1]) + atoi(argv[2]);
printf("HIJO %d \n",num);
exit(num);
}
default:
{
/* El padre recibe con el wait lo devuelto por el hijo en el exit y lo imprime por pantalla */
wait(&estado);
error=WEXITSTATUS(estado); //entrega los 8 bits más bajos de estado
printf("\nPADRE la suma de los hijos es: %d\n",error);
}
}
}
:mrgreen: :mrgreen:
-
Hola de nuevo
Me dejaron de tarea lo siguiente...
Investigar cuáles son los tipos de señales POSIX y escribir 2 programas que de ejemplo.
Hasta ahora sólo he leído unos ejemplos de la función...
#include <signal.h>
int kill (pid_t pid,int sig)
Y las señales que linux maneja son las siguientes...
(http://img138.imageshack.us/img138/2203/image004un5.jpg)
Al usar 2 de esas señales con kill, ¿ya estaría cumpliendo con mi tarea? Es que no conozco bien eso del POSIX y no quiero equivocarme. :oops:
Gracias
-
Hola
Aparte de la pregunta de arriba, tengo otra pregunta. Escribí un programa en linux que indica si un proceso existe en ejecución o no. El programa al terminar de ejecutarse entrega un 0 si el proceso existe o un 1 si no existe.
Lo entrega usando un exit(); al final del programa. Luego viene mi duda, tengo que hacer un shell script que haciendo uso de mi programa, indique al usuario si el proceso existe, leyendo la salida de exit.
Intenté hacer el shell script de la siguiente manera...
#!/bin/bash
salida=` ./existe 876`
echo salida = $salida
En donde " ./existe 876" es el programa y recibe 876 como el proceso a buscar. Pero lo que se deposita en salida no es la salida de exit del programa existe, es un revoltijo de caracteres de salida, pero nada que ver con salida uno o cero.
¿Qué puedo usar para leer la salida del programa en el shell? :roll:
Gracias
PD Adjunto el código del programa existe.c por si sirve para ayudarme =)
Edito:
Perdón ya lo encontré en internet...
http://www.comp.nus.edu.sg/~tanyeefa/cs1102c/mini0002.html
El script modificado queda así...
#!/bin/bash
./existe 22774
salida=$?
echo salida = $salida
:mrgreen:
-
Bueno, ya regresé con otra súper duda.
Estoy resolviendo un examen y una pregunta dice...
Escriba un programa que reciba como argumento una dirección IP y envíe una
llamada broadcast a toda la red solicitando la dirección MAC asociada a la IP indicada
como argumento. El host cuya dirección IP coincida con la petición enviada, contestará
con su dirección MAC. El programa deberá de recibir el mensaje de respuesta y
mostrará la dirección MAC por la salida estándar (pantalla).
Lo que tengo que usar es un socket y mucho ingenio, porque hasta ahora no he encontrado el cómo hacerlo. Investigué mucho sobre cómo se obtiene la MAC conociendo la IP, se debe usar el protocolo ARP, pero todo lo que encontré fue teoría y solo un programa...
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netdb.h>
int _get_MAC(char *addr,char *dport) {
int sock,sockfd, n;
char buffer[2048];
unsigned char *iphead, *ethhead;
struct hostent *he;
struct sockaddr_in their_addr; // connector's address information
// struct ifreq iface;
// struct sockaddr_in *addr;
struct ether_addr ether;
if ( (sock=socket(PF_PACKET, SOCK_RAW,htons(ETH_P_IP)))<0) {//
perror("socket");
exit(1);
}
if ((he=gethostbyname(addr)) == NULL) { // get the host info
perror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(atoi(dport)); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct
if (connect(sockfd, (struct sockaddr *)&their_addr,
sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
while (1) {
if (n = recvfrom(sock,buffer,2048,0,NULL,NULL)== -1) {
perror("recvfrom");
close(sock);
exit(1);
}
// n = recv(sock,buffer,2048,0);
ethhead = buffer;
if (ethhead != NULL)
{
printf("Source MAC address: "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
ethhead[0],ethhead[1],ethhead[2],
ethhead[3],ethhead[4],ethhead[5]);
printf("Destination MAC address: "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
ethhead[6],ethhead[7],ethhead[8],
ethhead[9],ethhead[10],ethhead[11]);
}
iphead = buffer+14; /* Skip Ethernet header */
if (*iphead==0x45) { /* Double check for IPv4
* and no options present */
printf("Source host %d.%d.%d.%d\n",
iphead[12],iphead[13],
iphead[14],iphead[15]);
printf("Dest host %d.%d.%d.%d\n",
iphead[16],iphead[17],
iphead[18],iphead[19]);
printf("Source,Dest ports %d,%d\n",
(iphead[20]<<8)+iphead[21],
(iphead[22]<<8)+iphead[23]);
printf("Layer-4 protocol %d\n",iphead[9]);
}
}
return 0;
}
int main(int argc, char **argv)
{
// cc=argv[1];
_get_MAC(argv[1],argv[2]);
return 0;
}
El programa compila correctamente con unas modificaciones pequeñas, pero no se ejecuta bien ya que el parámetro SOCK_RAW del primer socket es de nivel root y pues no me da chance.
¿Alguien conoce un método fácil para resolver mi problema?
Está muy difícil la pregunta del examen ya que el maestro no da bien las clases, pero bueno, doy por hecho que esa ya la tuve mal. Al menos ya resolví 5 de 6 preguntas :mrgreen:
-
Hola
El maestro ya nos dio la solución al problema...
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define ETH "eth0"
struct msgARP
{
unsigned char destinoEthernet[6];
unsigned char origenEthernet[6];
unsigned short tipoEthernet;
unsigned short tipoHardware;
unsigned short protocolo;
unsigned char longitudMAC;
unsigned char longitudRED;
unsigned short tipoARP;
unsigned char origenMAC[6];
unsigned char origenIP[4];
unsigned char destinoMAC[6];
unsigned char destinoIP[4];
};
int main (int argc,char *argv[])
{
struct msgARP msg;
struct ifreq ifr;
struct sockaddr sa;
int s,optral,n;
unsigned char ip[4];
/*
Se define un socket SOCK_PACKET para que TCP/IP no
incluya información adicional en las cabeceras. Con lo
que se tiene el control de los formatos del mensaje
*/
//Abriendo el socket
if((s=socket(PF_INET,SOCK_PACKET,htons(ETH_P_ARP)))<0)
{
perror("Socket");
exit(1);
}
//permitir el envío broadcast
optral=1;
if(setsockopt(s,SOL_SOCKET,SO_BROADCAST,&optral,sizeof(optral))<0)
{
perror("setsockopt");
exit(1);
}
/*obtención de la dirección IP y MAC de nuestra tarjeta*/
strcpy(ifr.ifr_name,ETH);
if(ioctl(s,SIOCGIFHWADDR,&ifr)<0)
{
perror("ioctl");
exit(1);
}
/*Se copia la dirección MAC al campo correspondiente de la cabecera ARP
y de la trama ethernet
*/
bcopy(&ifr.ifr_hwaddr.sa_data,&msg.origenMAC,6);
bcopy(&ifr.ifr_hwaddr.sa_data,&msg.origenEthernet,6);
/*Se obtiene la dirección IP asociada a la tarjeta de red*/
strcpy(ifr.ifr_name,ETH);
if(ioctl(s,SIOCGIFADDR,&ifr)<0)
{
perror("ioctl");
exit(1);
}
/*Copiar la dirección IP al campo de la cabecera ARP*/
bcopy(&ifr.ifr_addr.sa_data[2],&msg.origenIP,4);
/*Como dirección MAC de destino para la trama Ethernet se establece
FF:FF:FF:FF:FF:FF para realizar un broadcast*/
memset(&msg.destinoEthernet,0xff,6);
/*En la trama Ethernet se indicará que se transporta un mensaje
ARP, para que al recibir la trama cualquier estación destino sepa a
quién enviar los datos en el nivel superior*/
msg.tipoEthernet=htons(ETH_P_ARP);
/*Tipo de red Ethernet*/
msg.tipoHardware=htons(ARPHRD_ETHER);
/*El protocolo a nivel de red es IP*/
msg.protocolo=htons(ETH_P_IP);
/*longitud de las direcciones físicas en este caso son 6,
ya que se representan de la forma XX:XX:XX:XX:XX:XX:*/
msg.longitudMAC=6;
/*longitud de las direcciones de red*/
msg.longitudRED=4;
/*tipo de mensaje ARP: solicitud o respuesta*/
msg.tipoARP=htons(ARPOP_REQUEST);
/*la dirección MAC de la máquina destino*/
bzero(&msg.destinoMAC,6);
/*la dirección IP de la máquina destino*/
inet_aton(argv[1],msg.destinoIP);
strncpy(ip,msg.destinoIP,4);
bzero(&sa,sizeof(sa));
strcpy(sa.sa_data,ETH);
if(sendto(s,&msg,sizeof(msg),0,(struct sockaddr *)&sa,sizeof(sa))<0)
{
perror("sendto");
exit(1);
}
do
{
bzero(&sa,sizeof(sa));
bzero(&msg,sizeof(msg));
n=sizeof(sa);
if(recvfrom(s,&msg,sizeof(msg),0,(struct sockaddr *)&sa,&n)<0)
{
perror("recvform");
exit(1);
}
if((ntohs(msg.tipoARP)==ARPOP_REPLY)&&!strncmp(ip,msg.origenIP,4))
{
fprintf(stdout,"Respuesta del equipo al que se llamó, la IP es %s y se corresponde con al MAC %02x:%02x:%02x:%02x:%02x:%02x\n",argv[1],msg.origenMAC[0],msg.origenMAC[1],msg.origenMAC[2],msg.origenMAC[3],msg.origenMAC[4],msg.origenMAC[5]);
}
}while(1);
/*se cierra el socket*/
close(s);
}
El programa también compila bien. Pero también manda error de socket, no tengo los permisos para correrlo; lo intenté correr en mi linux como administrador y tampoco dio resultado.
Necesito ayuda de alguien que tenga forma de ejecutarlo, por favor díganme si corre bien. Los pasos para correrlo son...
$ ./macaddress 192.168.1.254
En donde la IP es el equipo de quien quieren obtener la MAC address.
Necesito estar seguro de que el programa corre para aceptar tener mal esa respuesta en el examen, de lo contrario tomaré cartas en el asunto :mrgreen:
Adjunto el código fuente y el ejecutable. Gracias.
-
Puse
sudo ./macaddress 192.168.0.1
Y funcionó bien.
Saludos,
Miguel Ángel.
-
Puse
sudo ./macaddress 192.168.0.1
Y funcionó bien.
Saludos,
Miguel Ángel.
Hola Miguel
¿Cómo lo ejecutaste si nadie ha descargado el ejecutable del post de arriba?
Ejecuté lo siguiente y pues no sé para qué sirve el "sudo"
$ sudo ./macaddress localhost
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
Password:
Sorry, try again.
Password:
sudo: 1 incorrect password attempt
[svillafuertea08@cluster16 a08]$
No tengo acceso root al servidor linux :(
-
Cuando lo probé no estaba "identificado" por lo que no vi los adjuntos. Lo que hice fue pegar el código en el gedit, guardarlo como macaddress.c y ejecutar gcc -o macaddress macaddress.c, luego lo probé:
ma4826@maamd:~$ gcc -o macaddress macaddress.c
ma4826@maamd:~$ ./macaddress 192.168.0.1
Socket: Operation not permitted
ma4826@maamd:~$ sudo ./macaddress 192.168.0.1
[sudo] password for ma4826:
Respuesta del equipo al que se llamó, la IP es 192.168.0.1 y se corresponde con al MAC 00:18:e7:f8:18:04
Saludos,
Miguel Angel.
-
Gracias Miguel
Ahorita regresé de linux en mi pc y corrió muy bien con el sudo, incluso el programa que había publicado anteriormente también corrió muy bien.
De haber sabido que existía el sudo, habría tenido la oportunidad de entregar el programa antes :8}
Me gustaría haber tenido un mejor profesor de Linux :?
-
Oh, recién leo este hilo y también estoy dando algunos pasitos, en mis escasos tiempos libres, para aprender C/C++ bajo linux.
De haber sabido que existía el sudo, habría tenido la oportunidad de entregar el programa antes :8}
De todas formas miguel, el sudo por si solo no sirve para nada si tu usuario no tiene permiso para adquirir permisos de root. Para ello debe estar en el listado de usuarios que pueden usar sudo o "sudoers list".
En cuanto a averiguar el Mac Address, tu profesor tal vez debió explicarles el Comando ARP que es independiente del Sistema Operativo .
-
Hola Mauricio
El profesor da las clases de manera súper aburrida y dejó el examen con esa pregunta, sin siquiera darnos las bases. Yo investigué todo, incluso como armar el paquete ARP, pero no supe cómo echar a andar el proyecto. También nos dejó otra pregunta del examen... semáforos como mecanismos IPC, pero tampoco la supe hacer.
Estoy aprendiendo mucho por mi cuenta, pero la clase y la experiencia pudo haber sido mejor si el profesor fuera de mejor calidad.
-
Estoy aprendiendo mucho por mi cuenta, pero la clase y la experiencia pudo haber sido mejor si el profesor fuera de mejor calidad.
Oh, por supuesto. Un buen profesor allana terreno, de eso no hay dudas, si solamente se dedica a tirar tarea, para eso que te pase las clases por mail y estudias en tu casa.
-
jaja
pues el examen fue para hacerse en casa :D
-
jaja
pues el examen fue para hacerse en casa :D
jejej, y cambiando de tema o siguiendolo. ¿Qué ide te gusta para Linux? Yo me bajé el CodeBlocks y pinta ser muy bueno pero no lo he probado.
-
¿Sabes que es lo más chistoso? Que no corro Linux para compilar mis programas :D
Utilizo una herramienta llamada SSH Secure Shell desde Windows XP para conectarme al servidor linux de mi escuela. Usando la misma herramienta subo mis archivos y los compilo vía cc, por ejemplo, cc holamundo.c -o hola.exe.
Me da flojera correr linux en mi pc porque es muy simple y en windows tengo todo a la mano, incluso la música para programar a gusto 8)
Para editar mis códigos utilizo el software llamado Neoxen Qwined, que colorea al estilo del Geshi del foro, los códigos fuente, ya sea .c o de otros como matlab.
Aquí unas fotos para que veas como trabajo.
(http://img241.imageshack.us/img241/8660/dibujosz0.th.jpg) (http://img241.imageshack.us/img241/8660/dibujosz0.jpg)
(http://img241.imageshack.us/img241/4112/dibujo2jx7.th.jpg) (http://img241.imageshack.us/img241/4112/dibujo2jx7.jpg)
(http://img98.imageshack.us/img98/2600/dibujo3yl0.th.jpg) (http://img98.imageshack.us/img98/2600/dibujo3yl0.jpg)
También cuando compilo software para mi nintendo, uso windows :D
-
¿Sabes que es lo más chistoso? Que no corro Linux para compilar mis programas :D
Utilizo una herramienta llamada SSH Secure Shell desde Windows XP para conectarme al servidor linux de mi escuela. Usando la misma herramienta subo mis archivos y los compilo vía cc, por ejemplo, cc holamundo.c -o hola.exe.
Pero si usas ssh para conectarte al servidor y por las imágenes que veo es un Unix también. Simplemente te conectas en forma remota pero estás compilando en destino o no? es que si ejecutas gcc nativo de windows te generará código para windows y no para linux. Salvo que no prueben luego el programa, no se.
Me da flojera correr linux en mi pc porque es muy simple y en windows tengo todo a la mano, incluso la música para programar a gusto 8)
Ja, pero si mp3 podes oir en linux también :mrgreen: :mrgreen:
El día que tenga mi nueva web al aire (que al paso que voy será por el 2022), allí compartiré mi afición por linux y las herramientas y cosas que nos brinda para hacernos más fácil la vida. :mrgreen:
-
Ah qué bien, ya te hacía falta un sitio web.
Pues tendrás que convencerme de que Linux es mejor que Windows, esperemos que tu web surta efecto :mrgreen:
-
Ah qué bien, ya te hacía falta un sitio web.
:mrgreen: :mrgreen:
Pues tendrás que convencerme de que Linux es mejor que Windows, esperemos que tu web surta efecto :mrgreen:
Oh, pero la idea no es convencer a nadie, a lo sumo mostrar lo que brindan otras plataformas y 'persuadirlos' de que hay otras alternativas. Hay un mundo más allá de windows... sobre todo para los que nos gustan los fierros, los sistemas embebidos y el software en general.
-
Bueno, entonces tendrás que persuadirme amigo Mauricio :D porque hasta ahora no le he agarrado gusto a Linux. :x
-
Bueno, entonces tendrás que persuadirme amigo Mauricio :D porque hasta ahora no le he agarrado gusto a Linux. :x
Oh, pero si tienes esa actitud no lo uses :) :) No hay peor cosa que iniciarte en un nuevo sistema operativo con esa actitud jeje. Es un sano consejo el que te doy, instálalo cuando te canses de cuelgues, bloqueos y cosas cerradas de tu Windows y quieras tener un control más profundo de tu pc. :) :)
Si algún día tienes una empresa... también deberás pensar bien qué usar ya que tener las cosas legales cuesta muuucho dinero . :mrgreen:
-
jejej
no es que tenga una actitud en contra de linux, pero es que me ha dado muchos problemas, principalmente con lo de mis clases de programación :D , pero ya luego se me olvidará y linux será mi amigo de nuevo. 8)
-
jejej
no es que tenga una actitud en contra de linux, pero es que me ha dado muchos problemas, principalmente con lo de mis clases de programación :D , pero ya luego se me olvidará y linux será mi amigo de nuevo. 8)
Jeje, bueno, en ese caso... sí será tu amigo. Hay muchas alternativas para quien quiere linuxear o bien unixear. Tenes también el FreeBSD que tiene muy buena crítica también.