Cvičenie 2 - Vytvorenie procesu
Pri riešení tohto cvičenia Vám, možno pomôžu:
Pripomenutie vytvorenia nového projektu v prostredí Microsoft Visual
Studio:
- Rozbehnite na počítači v učebni prostredie Microsoft Visual
Studio
- Vytvorte vo Visual Studiu nový projekt.
- File/New/Project,
- vyberte Windows Console Application,
- dole prípadne zmeňte Name a Location (nepovinné), stlačte
OK.
Ukážka 1 - vyvolanie Notepadu z programu v Pythone:
import subprocess
def edituj(text):
with open('pom.txt',mode='w') as f:
f.write(text)
res=subprocess.run(['notepad','pom.txt'])
if res.returncode == 0:
for li in
open('pom.txt'):
print(li,end='')
else:
print('CHYBA',res)
Ukážka 2 - vyvolanie Notepadu z programu vo Windows v C:
#include <iostream>
#include "windows.h"
int main()
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
HANDLE proc;
DWORD exitCode;
FILE* f;
char buff[1025];
// Zapisme nieco do suboru text.txt
fopen_s(&f,"e:\\text.txt", "w");
fprintf(f, "test");
fclose(f);
ZeroMemory(&pi, sizeof pi); //
inicializacia premennej pi
ZeroMemory(&si, sizeof si); //
inicializacia premennej si
si.cb = sizeof
si;
// vytvorime novy proces s
beznymi nastaveniami
if (CreateProcessA(NULL, (char *)
"notepad e:\\text.txt", NULL, NULL, false, NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi))
{
proc =
pi.hProcess;
//
v pi.hProcess sme dostali identifikacne cislo (handle) noveho
procesu
if
(WaitForSingleObject(proc, INFINITE) !=
WAIT_FAILED) // cakame na skoncenie procesu
{
GetExitCodeProcess(proc, &exitCode);
// ak cakanie neskoncilo chybou, tak prevezmeme
ukoncovaci kod
printf("ExitCode = %d\n", exitCode);
// a vypiseme ho
}
CloseHandle(proc);
//
oznamime op. systemu, ze uz nepotrebujeme cislo procesu
CloseHandle(pi.hThread);
// oznamime op. systemu, ze
uz nepotrebujeme cislo jeho hlavneho threadu
}
// zobrazme zeditovany subor
text.txt
fopen_s(&f, "e:\\text.txt", "r");
while (fgets(buff, sizeof buff, f) !=
NULL)
printf(buff);
fclose(f);
return 0;
}
Vyskúšajte si spustiť túto ukážku.
Ukážka 3 - vytvorenie nového procesu v Linuxe v C:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main( void ) {
FILE *f;
int stat;
char buff[1025];
f=fopen("text.txt", "w");
fprintf(f, "test\n");
fclose(f);
int pid = fork();
// vytvorime synovsky proces s identickym programom
if ( pid == 0 ) {
// sme v synovskom
procese: zmen program za iny
execlp("gedit","gedit","text.txt", (char *) NULL); //
prvy parameter je meno suboru,
// ak nema uvedenu cestu, tak sa hlada v path,
// druhy parameter je rovnaky ako prvy (stane sa z neho argv[0])
// dalsie parametre su parametre prikazovaho riadku
// posledny musi byt NULL
exit(127);
// skonci s kodom 127, sem prideme len ked sa execlp nepodari
} else if (pid < 0)
// nastala chyba:
synovsky proces sa nepodarilo vytvorit, pid je cislo chyby
printf("Chyba
%d\n",pid);
else {
// sme v otcovskom
procese: pid je identifikator synovskeho procesu
waitpid(pid,&stat,0);
printf("Exit status:
%d\n\n",WEXITSTATUS(stat));
f=fopen("text.txt",
"r");
while (fgets(buff,
sizeof buff, f) != NULL)
fputs(buff,stdout);
fclose(f);
}
return 0;
}
Kompilovanie a spustenie v príkazovom riadku Linuxu
(predpokladáme, že program ste uložili do súboru s názvom proc.c
ak to tak nie je, tak prispôsobte príkazy vami zvolenému menu
alebo súbor premenujte):
gcc proc.c -o proc
./proc
Odbočenie - práca s reťazcami v C (bude to treba pre úlohu 2 a 3)
Ukážka čítania reťazcov, prevodu reťazca na celé číslo a
zreťazenia reťazcov.
Pre Visual studio:
#include <iostream>
int main()
{
char x[11];
scanf_s("%10s",x,11); // cislo 10
v "%10s" hovori kolko znakov precitat,
// cislo 11 (treti parameter) hovori, ake velke je
pole (musi mat miesto aj na koncovu nulu)
printf("%s\n", x);
printf("%d\n", atoi(x));
char y[20];
strcpy_s(y, "cislo je: ");
strcat_s(y, x);
printf("%s\n", y);
}
Pre gcc (teda standardne C napr. v Linuxe alebo CLione):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char x[11];
scanf("%10s",x); // scanf
nepouziva treti parameter, ale je preto NEBEZPECNY lebo nepozna
dlzku premennej x
printf("%s\n", x);
printf("%d\n", atoi(x));
char y[20];
strcpy(y, "cislo je: ");
strcat(y, x);
printf("%s\n", y);
}
Úloha 1:
Spustite si Linux (alebo MacOs, ak mate na cvičení svoj Mac),
Zoberte Ukážku 1 a skúste ju rozchodiť v Linuxe.
Budete musieť riešit, že v Linuxe nie je Notepad.
MacOS: V macOS je vyvolanie GUI programu z iného programu trocha
zložitejšie, pozrite sem,
aj to nerozbeháte tak sa spýtajte cvičiaceho.
Úloha 2:
(V Linuxe, macOS alebo vo Windows, podľa Vášho výberu)
Keď programujeme v C, tak exitcode procesu je výsledok funkcie main().
Pomocou tejto novej vedomosti naprogramujte dva programy:
- Jeden prečíta z klávesnice číslo a to číslo odovzdá ako
výsledok svojho main()
- Druhý program spustí prvý program a vypíše jeho exitcode
(použite kód z Ukážky 2 alebo Ukážky 3 a zmeňte ho pre nové
potreby)
- Rady:
Číslo zo štandardného vstupu prečíta funkcia scanf
(prevedie znaky na číslo, je to akoby opak printf), vo Visual
Studiu ale musíte použiť jej "safe" verziu scanf_s, viď
ukážka v časti Odbočenie.
Linux: Prvý parameter funkcie execlp je meno súboru, teda môže
obsahovať aj cestu.
Pomôcky a rady pre Visual Studio (a iné integrované prostredia) :
- Tie dva programy musíte spraviť ako dva projekty,
inak sa vám nevytvoria dva vykonateľné súbory (.exe vo Windows).
- Nájdite, kde je vytvorený vykonateľný súbor (exe) z prvého
programu (vo Visual Studiu hľadajte adresár Debug v adresári
projektu) a dajte ho niekam na "pekné" miesto, napríklad na e:\,
aby ho druhý program mohol vyvolať bez dlhočiznej cesty.
- Nezabudnite, že vo vnútri reťazcov musíte každé
opačné lomítko napísať dvakrát.
Úloha 3:
Keď zadefinujete funkciu main ako
int main(int argc, char *argv[])
tak v argc dostanete počet
parametrov príkazového riadku, ktorým bol program vyvolaný a v argv
sú uložené parametre ako pole reťazcov (argv[0] je meno programu, až
argv[1] je prvý parameter).
Pomocou tejto novej vedomosti naprogramujte programy:
- Jeden, ak je spustený s paramtrami, tak zoberie prvý z nich,
prevedie ho na celé číslo, zistí, či je prvočíslo (nejakým
najjednoduchším spôsobom). Ak je prvočíslo tak skončí s exitcode
0, inak s exitcode 1. Ak dostane zlý vstup (pre zlý string
funkcia atoi vráti 0 a nula aj
tak nie je dobrý vstup), alebo žiadny vstup, tak skončí s
exitcode 127.
- Druhý program prečíta číslo z klávesnice zavolá prvý program s
daným číslom ako prvým paramtrom príkazového riadku. Podľa
exitcode napíše "je prvocislo", "nie je prvocislo" alebo
"nastala chyba".
- Rady:
Prvý program musí previesť reťazec argv[1] do čísla, na to je v
C funkcia atoi, viď ukážka v
časti Odbočenie
Druhý program musí odovzdať prvému číslo ako reťazec, takže
vlastne môže čítať reťazec a ten odovzdať.