PDA

View Full Version : [C e Linux] Come si fa?


Corvo80
22-08-2005, 15:42
Salve a tutti, premesso che sono solo alle prime armi con la programmazione in C mi chiedevo se poteste darmi una mano. Essenzialmente dovrei scrivere un semplice programmino che stampi sullo schermo un istogramma orizzontale del numero di processi per ogni utente, del tipo:

root: ******
mario: ***
antionio: ****
etc...

Sia chiaro: non voglio che mi facciate voi il programma, vorrei solo qualche dritta dato che sto navigando in alto mare. Vi ringrazio per qualunque consiglio possiate offrirmi.

:D

RaouL_BennetH
22-08-2005, 16:01
in queste cose io non sono molto esperto,però mi sembra una cosa simile al comando ps con le relative opzioni.Di sicuro c'è il sorgente a disposizione,potresti utilizzarlo come base per il tuo studio. :)

ilsensine
22-08-2005, 16:03
Dai una occhiata in /proc, alle sottodirectory con un numero come nome. Ciascuna corrisponde a un processo, e il proprietario della directory è il proprietario del processo.

Corvo80
22-08-2005, 16:09
in queste cose io non sono molto esperto,però mi sembra una cosa simile al comando ps con le relative opzioni.Di sicuro c'è il sorgente a disposizione,potresti utilizzarlo come base per il tuo studio. :)

Veramente contavo proprio di usare ps come system call all'interno del programma, solo che non mi pare ci siano abbastanza opzioni per quello che devo fare io...

:stordita:

Dai una occhiata in /proc, alle sottodirectory con un numero come nome. Ciascuna corrisponde a un processo, e il proprietario della directory è il proprietario del processo.

Grazie ma a questo punto è come usare il comando ps... ;)

ilsensine
22-08-2005, 16:14
ps non è una syscall, ma puoi invocarlo da programma e reindirizzarne l'output su un descrittore aperto dal programma. Stessa cosa puoi fare con top.
Poi però devi interpretare da programma l'output, che è stampato in un formato umanamente leggibile.

Corvo80
22-08-2005, 16:28
Ok ho elaborato un'idea di algoritmo (in linguaggio ipotetico), ditemi se concettualmente può fungere:

1) Stampa il risultato di ps a file1 (con tutte le opzioni necessarie)
2) Pulisci file1 in modo da lasciare solo gli username (1 riga per ogni processo)
3) Considera il primo user
4) Richiamo a comando shell "grep" per sapere quante volte esso compare nel file, ovvero quanti processi ci sono per quell'user.
5) Append a file2 del tipo: "tizio: *********** " tramite ciclo for e a capo.
6) Cancella le prime righe su file1 (quelle dell'user precedentemente trovato)
7) Se file1 non è vuoto torna a punto 3) [ovviamente parliamo di programmazione strutturata quindi questa schifezza verrà tradotta in un ciclo while... ^_^]
8) Stampa a schermo file2

ilsensine
22-08-2005, 16:49
1) Stampa il risultato di ps a file1 (con tutte le opzioni necessarie)
Ci sono metodi MOLTO più eleganti di insozzare il file system con file temporanei ;)

4) Richiamo a comando shell "grep" per sapere quante volte esso compare nel file, ovvero quanti processi ci sono per quell'user.
Se intendi usare grep e magari anche sed o altro per fare il "lavoro sporco", puoi anche considerare l'uso di un linguaggio di script (perl, bash, ecc.) senza scomodare un linguaggio compilato...

Corvo80
22-08-2005, 16:52
Ci sono metodi MOLTO più eleganti di insozzare il file system con file temporanei ;)

Ecco, ad esempio? Cmq contavo di farlo cancellare al termine della computazione...

Se intendi usare grep e magari anche sed o altro per fare il "lavoro sporco", puoi anche considerare l'uso di un linguaggio di script (perl, bash, ecc.) senza scomodare un linguaggio compilato...

Eh... purtroppo devo farlo in C. Cmq per il resto dovrebbe funzionare, no?

Corvo80
24-08-2005, 10:45
Ok ho fatto. Il programma è funzionante anche se un po'sporco... Ora però dovrei apportare una modifica:

dovrei fare in modo che esso accetti come argomento un nome utente particolare e, in questo caso, stampare una stringa del tipo:

"utente tizio n processi"

Ovviamente devo fare riferimento ad argc per sapere se ci sono argomenti e ad argv[1] per leggere il primo, il problema è che non riesco a comparare la stringa contenuta in argv[1] con l'array di caratteri che leggo dal file...

Qualche idea? :confused:

ilsensine
24-08-2005, 10:55
ps uxU pippo
Restituisce solo i processi dell'utente pippo

Corvo80
24-08-2005, 11:30
ps uxU pippo
Restituisce solo i processi dell'utente pippo

Ok ma il problema è lo stesso: come faccio a passare allo script il nome "pippo" che il programma c deve leggere dall'argomento argv[1]?

:mbe:

ilsensine
24-08-2005, 11:33
Formatti con snprintf la stringa da passare alla chiamata system/exec.

Corvo80
24-08-2005, 11:46
Grazie, credo fosse la risposta che cercavo. Ora purtroppo devo uscire ma questo pomeriggio provo.

PS Devo includere qualche libreria particolare?

RaouL_BennetH
24-08-2005, 12:27
PS Devo includere qualche libreria particolare?

Ovvio :O


#include <ilsensine.h>


:D

Corvo80
24-08-2005, 14:30
Ok grazie ancora.

Qualcuno mi spiega la sintassi di snprintf e sprintf? (n° e tipo di argomenti, come si usa, etc...) purtroppo non ho un manuale di C, ho provato a cercare in Internet ma non ho trovato...

:(

fantoibed
24-08-2005, 14:41
Qualcuno mi spiega la sintassi di snprintf e sprintf? (n° e tipo di argomenti, come si usa, etc...) purtroppo non ho un manuale di C, ho provato a cercare in Internet ma non ho trovato...

http://www.die.net/doc/linux/man/man3/snprintf.3.html

Tra sprintf e snprintf ti consiglio sempre la seconda.

PS: Occhio ai buffer overflow!

Corvo80
24-08-2005, 15:11
Come al solito siete stati gentilissimi.

Ora la prova del nove...

Se ho capito bene, per far si' che la stringa contenuta in argv[1] sia formattata e reperibile dovro- scrivere:

sprintf(argomento, argv[1]);

essendo argomento un puntatore a caratteri, giusto?

fantoibed
24-08-2005, 15:21
Manca il formato.

sprintf(argomento, formato, variabile);

sprintf(argomento, "%s", argv[1]);

Ovviamente argomento dovrà contenere abbastanza spazio, sia che l'allocazione sia stata fatta staticamente che dinamicamente.

Se hai bisogno di un maggiore controllo sugli argomenti passati da linea di comando, ti consiglio di guardare anche getopt():

http://www.die.net/doc/linux/man/man3/getopt.3.html

Corvo80
24-08-2005, 15:49
segmentation fault

:mc: :muro:

Corvo80
24-08-2005, 16:05
Ok mi sembra di impazzire: ho risolto il problema della segmentation fault ma ora ho un altro problema:

ho lanciato il programma con argomento knoppix:

a.out knoppix

ora, fila tutto liscio come l'olio fino a...

if (argomento == outp)
{
...
}

ma il risultato della condizione e' false

questo non ha senso, ho anche provato a far stampare i valori di argomento e outp prima del check e sono identici! Come mai?!!!

:muro:

fantoibed
24-08-2005, 16:12
Il segmentation fault era quasi sicuramente dovuto ad un overflow sui buffer... ;)

Per il confornto, devi usare strcmp se vuoi confrontare le due stringhe (quello che hai scritto tu è un confronto sul valore dei puntatori, non sul contenuto delle stringhe a cui puntano).

http://www.die.net/doc/linux/man/man3/strcmp.3.html

Corvo80
24-08-2005, 16:26
Azz! Devo proprio comprarmi un benedetto manuale... -.-'

Grazie ancora 100,000 di tutte le dritte che mi avete dato, credo che non mi serva altro. Domani mi rimetto al lavoro... (oggi ho il cervello fuso).

Corvo80
25-08-2005, 09:30
Credo seriamente che il mio PC sia posseduto... Guardate un po'qua:

sprintf(argomento,"%s", argv[1]);
j = strcmp(argomento, outp);
if (j == 0);
{
printf("utente ");
printf(outp);
printf(" %i processi\n", count);
}

Il problema e' duplice:

1) argomento e outp sono identici ma strcmp non da' come risultato 0
2) qualunque risultato dia strcmp e' indifferente perche' il codice entro le graffe dell' if viene cmq sempre eseguito...

Qual' e' l'arcano, stavolta? :muro:

fantoibed
25-08-2005, 10:07
Sono con Windows, quindi tralascio la parte di dump dei processi:

#include <stdio.h>

int main(int argc, char *argv[])
{
char* outp="prova";
unsigned int count=666, j=0;

if ((j=strcmp(argv[1], outp))==0)
{
printf("%s %s %d %d", argv[1], outp, count, j);
}
return 0;
}

C:\Documents and Settings\fantoibed\Documenti\dev>"Project 1.exe" prova
prova prova 666 0

Corvo80
25-08-2005, 10:22
if (j=strcmp(argv[1], outp));

dovrebbe essere...

if (j==strcmp(argv[1], outp));

?

fantoibed
25-08-2005, 10:26
if (j=strcmp(argv[1], outp));

dovrebbe essere...

if (j==strcmp(argv[1], outp));

?

No. Piuttosto intendevo questo: if ((j=strcmp(argv[1], outp))==0){...}
Correggo nel post precedente...

Corvo80
25-08-2005, 10:27
Ok funziona ma togli il ";" dalla riga dell'if... ^_^

fantoibed
25-08-2005, 10:29
Ok funziona ma togli il ";" dalla riga dell'if... ^_^

C'era un ; in più dopo l'if... Colpa della fretta. Ora rifai il copia e incolla e dovrebbe andare.

Corvo80
25-08-2005, 10:32
Cmq non capisco perchè il mio codice non funzionasse... non fa essenzialmente la stessa cosa?

:confused:

fantoibed
25-08-2005, 10:39
Cmq non capisco perchè il mio codice non funzionasse... non fa essenzialmente la stessa cosa?

:confused:

Anche nel tuo avevi messo un ";" in più dopo l'istruzione if... ;)

Corvo80
25-08-2005, 11:15
Anche nel tuo avevi messo un ";" in più dopo l'istruzione if... ;)

OOOOOOOOOOOOPS!

:stordita: