|
[ glupi @ 05.05.2005. 09:29 ] @
| Imam program koji ispisuje 20 brojeva i onda ocekuje da ja upisem jedan broj koji se generira na osnovu tih 20. Sada ja hoću napraviti program koji ce ucitati tih 20 brojeva napraviti potrebne operacije i vratiti programu taj broj. Jedina meni poznata metoda je da sa popen-om otvorim taj program, ali problem je sto popen dozvoljava samo citanje ili pisanje u program, sto je za ovaj problem neprihvatljivo. Da li postoji neka druga funkcija/tehnika kojom bi mogao i citati output i pisati input programu? |
[ toroman @ 05.05.2005. 16:30 ] @
Čekaj malo!
Kako to misliš "popen podržava samo pisanje i čitanje iz programa" pa onda "da li postoji nešto što može da čita output i piše input u program" ?
Pa popen podržava i čitanje i pisanje ko što i sam kažeš, šta je onda problem? Pročitaš brojeve i onda upišeš rezultat i etc...
Izvinjavam se ako te nisam dobro shvation, pozdrav!
[ Mihajlo Cvetanović @ 05.05.2005. 17:28 ] @
Nisam ni ja odmah shvatio pa sam lepo pogledao MSDN i video da _popen
preusmerava ili stdin, ili stdout, ali ne moze oba (posto vraca samo
jedan hendl). Po svemu sudeci ne postoji standardno C/C++ resenje, ali
SDK funkcija CreateProcess prima sva tri hendla (stdin, stdout, stderr),
tako da treba nju koristiti.
[ glupi @ 05.05.2005. 18:30 ] @
Citat: SDK funkcija CreateProcess prima sva tri hendla (stdin, stdout, stderr)
Tako nesto bi mi trebalo samo pod linuxom.
[ toroman @ 07.05.2005. 00:38 ] @
epa, ja znam da u pythonu postoji funkcija
os.popen
i to nekoliko varijanti, stim da ova obična podržava i stdin i stdout,
valjda je tako i u cpp-u onda
[ Dejan Lozanovic @ 07.05.2005. 13:54 ] @
Citat: glupi: Imam program koji ispisuje 20 brojeva i onda ocekuje da ja upisem jedan broj koji se generira na osnovu tih 20. Sada ja hoću napraviti program koji ce ucitati tih 20 brojeva napraviti potrebne operacije i vratiti programu taj broj. Jedina meni poznata metoda je da sa popen-om otvorim taj program, ali problem je sto popen dozvoljava samo citanje ili pisanje u program, sto je za ovaj problem neprihvatljivo. Da li postoji neka druga funkcija/tehnika kojom bi mogao i citati output i pisati input programu?
Pa popen je malo "gospodsko" resenje jer pokrene nekoliko sistemskih poziva koje je za 90% programa dovoljno.
A sada da razjasnimo sistemske pozive osnova cele stvari je sistemski poziv pipe(man 2 pipe) on kreira dva fajl deskriptora(jedan za citanje drugi za pisanje). Znaci koliko ces puta pozivati pipe zavisi od toga koliko ti treba razlicitih veza preko kojih se odvija komunikacija.
Nakon sto si kreirao dovoljan broj pipe-ova, pozoves fork(man 2 fork), fork kreira novi proces na unix sistemima, novo kreirani proces(dete) je identican procesu koji ga je kreirao(roditelju) sa jedinom razlikom sto rezultat koji vraca fork (detetu vrati 0, a roditelju vrati broj procesa od deteta), sto znaci da fajl deskriptori koji su otvoreni i oba programa postoje.
Nakon forka treba u roditelju i detetu pozatvarati(man 2 close) one fajl deskriptore od pipe koji nam nisu potrebni(recimo u roditelju zatvorimo citanje, a u detetu pisanje za svaki par). Posle toga u detetu pozatvaras i one osnvone fajl deskriptore (0 stdin,1 stdour,2 stderr) i koristeci dup2 (man 2 dup2) namestis tvoje pipeove na zeljenje fajl deskriptore, nakon toga mozes da zatvoris one fajl deskrioptore sto su ti ostali od pipe-a u detetu,( jer si ih duplirao na ove standardne pa tako oslobadjas resurse)
I na kraju kada si sve zavrsio pozoves u detetu exec (izbegavaj system da koristis iz sigurnosnih razloga).
Ukoliko ti je nesto ostalo nejasno pitaj da dodatno objasnim
[ glupi @ 08.05.2005. 18:50 ] @
Hvala na odgovoru, ovaj kod odradjuje posao, samo read iz fajla radi probleme, nekad nece sve ucitat u buffer makar jer buffer 1000 karaktera pa moram 2 puta readat za po 15-20 karaktera.
Code:
#include <sys/types.h>
#include <unistd.h>
#define SIZE 1000
struct popen2
{
pid_t proc_pid;
int read, write;
};
int popen2(struct popen2 *pinfo)
{
pid_t p;
int pin[2], pout[2];
if(pipe(pin)) return -1;
if(pipe(pout)) return -1;
if((p=fork()) < 0) return p;
if(p == 0)
{
close(pin[1]);
dup2(pin[0], 0);
close(pout[0]);
dup2(pout[1], 1);
execl("/usr/bin/telnet", "telnet", "localhost", "25", 0);
exit(99);
}
pinfo->proc_pid = p;
pinfo->write = pin[1];
pinfo->read = pout[0];
return 0;
}
void wwrite(char *msg,struct popen2 *id)
{
int len=strlen(msg);
write(id->write,msg,len);
}
int main(void)
{
char buf[SIZE];
struct popen2 prog;
memset(buf,0,SIZE);
popen2(&prog);
read(prog.read,buf,SIZE);
printf("from: %s\n",buf);
wwrite("helo asda\n",&prog);
wwrite("QUIT\n",&prog);
memset(buf, 0, SIZE);
read(prog.read, buf,SIZE);
printf("from child: %s", buf);
memset(buf, 0, SIZE);
read(prog.read, buf,SIZE);
printf("from child: %s", buf);
memset(buf, 0, SIZE);
read(prog.read, buf,SIZE);
printf("from child: %s", buf);
close(prog.write);
kill(prog.proc_pid, 0);
return 0;
}
[ Dejan Lozanovic @ 09.05.2005. 22:00 ] @
Citat: glupi: Hvala na odgovoru, ovaj kod odradjuje posao, samo read iz fajla radi probleme, nekad nece sve ucitat u buffer makar jer buffer 1000 karaktera pa moram 2 puta readat za po 15-20 karaktera.
Pa realno velicina baffera nema mnogo veze sa tim, zamisli da citas recimo sa terminala i hoces da procitas 1000 bajtova a korisnik unese samo 10, read ce ti vratiti 10 bajtova, nece ostaviti program zaglavljenim dok ne napuni 1000 bajtova.
Ima jos jedna mala stvar koja mi bode oci ovakvom programu a vezana je za sistemsko programiranje, to je onaj deo oko exit(99); to je sve ok kada je u pitanju dete, medjutim tebi roditelj nigde ne obraca paznju na taj deo. Konkretno trebao bi da hvatas signal SIGCHLD (man 2 signal i man 7 signal) i da u njemu pozoves wait (man 2 wait) i uzmes status programa, i propisno odreagujes(tj u ovom konretnom slucaju je u pitanju zatvararanje glavnog programa naprimer)
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|