Pokročilé
IPC v Linuxu
Nový proces a vlákno | Nový proces a vlákno |
|
|
|
| Zhlédnutí: 2582 | ||||||||
| Napsal filbar | ||||||||
| Úterý, 10 červenec 2007 | ||||||||
| Aktualizováno ( Středa, 18 červenec 2007 ) | ||||||||
|
Tímto dílem začínáme nový seriál, ve kterém si ukážeme jak pod Linuxem programovat IPC(InterProcess Communication) aplikace, nebo-li programy, které mezi sebou komunikují. Naše příklady si budeme ukazovat na klasických Linuxových jazycích jako C a C++. V dnešním úvodním dílu si ukážeme jak rozdvojit původní proces a také jak si vytvoříme nové vlákno, abychom v následujících dílech měli mezi čím komunikovat. Nový procesProces lze rozdvojit velice jednoduše pomocí funkce fork, která vrací v případě úspěchu PID procesu potomka a 0 při běhu potomka. Při chybě vrací hodnotu -1 a nevytvoří se potomek. Nejjednodušší příklad vypadá následovně: #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { printf("Toto je původní proces před rozdvojením\n"); int pid=fork(); if(pid==0) { printf("Toto je potomek číslo %d\n",pid); } else { printf("Toto je původní proces číslo %d po rozdvojení\n",pid); } } Jako výstup po kompilaci g++ -o fork fork.cpp dostaneme:
Toto je původní proces před rozdvojením Na tomto příkladu je krásně vidět, jak fork vrací dvě hodnoty. Pokud je pid 0, pak pokračuje potomek, jinak rodičovský proces. Zajímavější bude, když budeme chtít mít tři potomky: #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { printf("Toto je původní proces číslo %d před rozdvojením\n",getpid()); int pid=fork(); if(pid==0) { printf("Toto je potomek číslo %d - %d \n",pid,getpid()); } else { printf("Toto je původní proces číslo %d po rozdvojení\n",getpid()); int pid1=fork(); if (pid1==0) { printf("Toto je druhý potomek číslo %d\n",getpid()); } } } Kód pro třetího potomka musíme umístit do části else ifu u prvního potomka, kdy vlastně běží původní proces. U druhého potomka již další else význam nemá, protože by opět běžel původní proces. Také byla pro přesvědčení přidáno volání fuknce getpid(), která vrací číslo aktuálního procesu. Nové vláknoProtože vytvoření nového procesu obvykle náročnější než vytvoření nového vlákna dáváme přednost právě vláknům. Vytvoření nového vlákna je o složitější, ale je přehlednější. Do parametru funkce pro vytvoření vlákna zadáváme také jméno funkce, která bude představovat co bude vlákno provádět. Prototyp vypadá následovně:
#include <pthread.h> Jako první zadáváme proměnnou typu pthread_t, která označuje jméno skupiny vláken. Dalším parametrem jsou atributy vlákna-nám prozatím stačí zde umísťovat NULL. Následující parametr je jméno funkce, která bude řídit provádění vlákna. Jak to funguje si ukážeme na příkladu, který vytvoří nové vlákno a vypíše v něm text:
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> void *vl1(void *par) { printf("Ahoj tady nove vlakno.\n"); printf("Prijat parametr %d.\n",*(int*)par); sleep(2); pthread_exit(0); } int main(void) { pthread_t vlakno; int ret; int a=10; ret=pthread_create(&vlakno,NULL,vl1,(void*)&a); if (ret == 0 ) { printf("Vlakno uspesne vytvoreno-predan parametr %d.\n",a); } else { printf("Vlakno se nepodarilo vytvorit!!!\n"); } pthread_join(vlakno,0); exit (0); } Kompilaci provedeme příkazem: g++ -o thread thread.cpp -D__USE_REENTRANT -lpthread Ve funkci main si nejprve definujeme proměnnou vlákno typu pthread_t, do které se ve funkci pthread_create uloží číslo vlákna. Dále si tvoříme dvě proměnné. Do proměnné ret ukládáme návratovou hodnotu vytváření vlákna. Při chybě se do ní uloží hodnota 0, což následně testujeme. U fuknce pthread_create bych ještě upozornil na způsob předávání parametrů vláknu. Musíme je předat před dereferenční operátor a ještě přetypovat na (void*). Samotná funkce provádějící se ve vlákně musí být také ukazatel na void. Dále první zpráva vypsaná na obrazovku upozorňuje ne nové vlákno a ve druhé si vypisujeme předaný parametr. Opět je nutné si všimnout použitého přetypování. Před ukončením vlákna ještě voláme funkci pthread_exit, do které předáváme návratovou hodnotu. Jedná se o ekvivalent funkce exit ukončující program. Vrátíme se do hlavní funkce main, kde si všimněte důležité funkce pthread_join, která pozastaví provádění hlavního programu, dokud není ukončeno vlákno. Při testování si jí zkuste zakomentovat a zjistíte, že se hlášky vlákna vůbec nevypíšou. Je tomu tak proto, že se náš velmi krátký hlavní program ukončí rychleji, než se stihnou začít provádět instrukce vlákna. V archivu v sekci Ke stažení/Soubory k článkům/Programování naleznete další variantu, kdy z prvního vlákna vytváříme vlákno další. Jedná se vlastně o obdobu jednoho vlákna. Žádné novinky zde již nejsou. Když umíme vytvářet nové procesy a vlákna, tak již příště můžeme pomocí roury začít mezi nimi začít posílat data. Rovněž se dostane na ještě jednu variantu vytváření nových procesů a to pomocí funkce exec.
Powered by !JoomlaComment 3.22
3.22 Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved." |
||||||||
| < Předch. |
|---|