Advertisement
Guest User

Untitled

a guest
Jun 27th, 2017
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.36 KB | None | 0 0
  1. /*!
  2.  
  3. * Dretve i procesi
  4.  
  5. */
  6.  
  7. #include "dretve_i_procesi.h"
  8.  
  9. #include <malloc.h>
  10.  
  11. #include <stdio.h>
  12.  
  13. #include <stdlib.h>
  14.  
  15. #include <sys/types.h>
  16.  
  17. #include <sys/wait.h>
  18.  
  19. #include <unistd.h>
  20.  
  21. #include <stdarg.h>
  22.  
  23. #include <sys/stat.h>
  24.  
  25. #include <fcntl.h>
  26.  
  27. /*!
  28.  
  29. * Sucelje za rad s procesima
  30.  
  31. */
  32.  
  33. static int postavi_kao_servis ();
  34.  
  35.  
  36.  
  37. /*!
  38.  
  39. * Stvaranje novog procesa dupliciranjem postojeceg
  40.  
  41. * \param funkc Funkcija koju ce novi proces izvoditi
  42.  
  43. * \param pparam Parametar za funkciju - pokazivac
  44.  
  45. * \param iparam Parametar za funkciju - broj
  46.  
  47. * \returns PID stvorenog procesa
  48.  
  49. */
  50.  
  51. pid_t stvori_proces_dijete ( void *funkcija, void *pparam, int iparam,
  52.  
  53. int servis )
  54.  
  55. {
  56.  
  57. pid_t pid;
  58.  
  59. void (*f) (void *, int);
  60.  
  61. pid = fork ();
  62.  
  63. if ( pid )
  64.  
  65. return pid;
  66.  
  67. /* treba li biti servis? */
  68.  
  69. if ( servis && postavi_kao_servis () )
  70.  
  71. {
  72.  
  73. perror ( "postavi_kao_servis" );
  74.  
  75. exit ( EXIT_FAILURE );
  76.  
  77. }
  78.  
  79. f = funkcija;
  80.  
  81. f ( pparam, iparam );
  82.  
  83. exit ( EXIT_SUCCESS );
  84.  
  85. }
  86.  
  87. /*!
  88.  
  89. * Stvaranje novog procesa pokretanjem programa
  90.  
  91. * \param br_arg Broj argumenata (svi su znakovni nizovi!)
  92.  
  93. * \param arg Prvi argument (ime datoteke s programom)
  94.  
  95. * \returns PID stvorenog procesa
  96.  
  97. */
  98.  
  99. pid_t stvori_novi_proces ( int servis, int br_arg, char *arg, ... )
  100.  
  101. {
  102.  
  103. va_list ap;
  104.  
  105. char *args[br_arg + 1];
  106.  
  107. pid_t pid;
  108.  
  109. int i;
  110.  
  111. pid = fork ();
  112.  
  113. if ( pid )
  114.  
  115. return pid;
  116.  
  117. args[0] = arg;
  118.  
  119. va_start ( ap, arg );
  120.  
  121. for ( i = 1; i < br_arg; i++)
  122.  
  123. args[i] = va_arg ( ap, char *); /* moglo je i arg[i] */
  124.  
  125. va_end ( ap );
  126.  
  127. args[br_arg] = NULL; /* mora zavrsavati s NULL */
  128.  
  129. /* treba li biti servis? */
  130.  
  131. if ( servis && postavi_kao_servis () )
  132.  
  133. {
  134.  
  135. perror ( "postavi_kao_servis" );
  136.  
  137. exit ( EXIT_FAILURE );
  138.  
  139. }
  140.  
  141. execvp ( args[0], args );
  142.  
  143. perror ( "execv" ); /* nema povratka iz execv osim kada ne uspije */
  144.  
  145. exit ( EXIT_FAILURE );
  146.  
  147. }
  148.  
  149. /*!
  150.  
  151. * Ceka na kraj procesa sa zadanim PID-om
  152.  
  153. * \param pid Pid procesa (ili 0, kada ceka bilo koje dijete)
  154.  
  155. * \returns status docekanog procesa, -1 u slucaju greske
  156.  
  157. */
  158.  
  159. int cekaj_kraj_procesa ( int pid )
  160.  
  161. {
  162.  
  163. int status;
  164.  
  165. if ( waitpid ( pid, &status, 0 ) < 0 )
  166.  
  167. return -1;
  168.  
  169. return status;
  170.  
  171. }
  172.  
  173. /*!
  174.  
  175. * Pomocna funkcija koja proces odvaja od konzole - postavlja kao servis
  176.  
  177. */
  178.  
  179. static int postavi_kao_servis ()
  180.  
  181. {
  182.  
  183. //printf ( "Nije implementirano!\n" );
  184.  
  185. return 0;
  186.  
  187. }
  188.  
  189.  
  190.  
  191. /*!
  192.  
  193. * Sucelja za rad s dretvama
  194.  
  195. */
  196.  
  197. static void *radna_dretva ( void *pskup );
  198.  
  199. /* lista opisnika skupova radnih dretvi */
  200.  
  201. static radne_dretve_t *rd_prvi = NULL, *rd_zadnji = NULL;
  202.  
  203. /* stati�ka inicijalizacija varijable zaklju�avanja (mutexa) */
  204.  
  205. static pthread_mutex_t rd_brava = PTHREAD_MUTEX_INITIALIZER;
  206.  
  207. /*!
  208.  
  209. * Stvara skup radnih dretvi
  210.  
  211. * \param broj Broj dretvi u skupu (koliko da ih stvori)
  212.  
  213. * \returns Pokazivac na opisnik skupa dretvi
  214.  
  215. */
  216.  
  217. void *stvori_radne_dretve ( int broj )
  218.  
  219. {
  220.  
  221. radne_dretve_t *dretve;
  222.  
  223. int i;
  224.  
  225. dretve = malloc ( sizeof (radne_dretve_t) + sizeof (pthread_t) * broj );
  226.  
  227. dretve->iddr = (pthread_t *) ( dretve + 1 );
  228.  
  229. dretve->broj = broj;
  230.  
  231. pthread_mutex_init ( &dretve->brava, NULL );
  232.  
  233. pthread_cond_init ( &dretve->red, NULL );
  234.  
  235. pthread_cond_init ( &dretve->gotovo, NULL );
  236.  
  237. dretve->prvi = dretve->zadnji = NULL; /*u po�etku je red poslova prazan*/
  238.  
  239. dretve->kraj = 0;
  240.  
  241. dretve->br_poslova = 0;
  242.  
  243. for ( i = 0; i < broj; i++ ) /* stvori radne dretve */
  244.  
  245. {
  246.  
  247. if ( pthread_create ( &dretve->iddr[i], NULL, radna_dretva,
  248.  
  249. dretve ) )
  250.  
  251. {
  252.  
  253. printf ( "Greska u stvaranju dretvi!\n" );
  254.  
  255. exit ( 1 );
  256.  
  257. }
  258.  
  259. }
  260.  
  261. /* dodaj skup dretvi u listu opisnika skupova dretvi */
  262.  
  263. pthread_mutex_lock ( &rd_brava );
  264.  
  265. if ( rd_zadnji == NULL )
  266.  
  267. rd_prvi = dretve;
  268.  
  269. else
  270.  
  271. rd_zadnji->iduci = dretve;
  272.  
  273. rd_zadnji = dretve;
  274.  
  275. dretve->iduci = NULL;
  276.  
  277. pthread_mutex_unlock ( &rd_brava );
  278.  
  279. return dretve;
  280.  
  281. }
  282.  
  283. /*!
  284.  
  285. * Radna dretva (kucanski poslovi cekanja i preuzimanja posla)
  286.  
  287. * \param odretve Opisnik skupa dretvi (kome dretva pripada)
  288.  
  289. * \returns NULL
  290.  
  291. */
  292.  
  293. static void *radna_dretva ( void *odretve )
  294.  
  295. {
  296.  
  297. radne_dretve_t *dretve;
  298.  
  299. posao_t *posao;
  300.  
  301. dretve = odretve;
  302.  
  303. pthread_mutex_lock ( &dretve->brava );
  304.  
  305. while ( dretve->kraj == 0 )
  306.  
  307. {
  308.  
  309. if ( dretve->prvi != NULL ) /* ima li poslova u redu? */
  310.  
  311. {
  312.  
  313. posao = dretve->prvi; /* uzmi prvi posao */
  314.  
  315. /* ažuriraj listu */
  316.  
  317. dretve->prvi = dretve->prvi->iduci;
  318.  
  319. if ( dretve->prvi == NULL )
  320.  
  321. dretve->zadnji = NULL;
  322.  
  323. /* prije obrade izadji iz monitora */
  324.  
  325. pthread_mutex_unlock ( &dretve->brava );
  326.  
  327. /* pocni obradu */
  328.  
  329. posao->funkcija ( posao->id, posao->pparam,
  330.  
  331. posao->iparam );
  332.  
  333. /* obrada je gotova */
  334.  
  335. pthread_mutex_lock ( &dretve->brava );
  336.  
  337. dretve->br_poslova--;
  338.  
  339. free ( posao );
  340.  
  341. /* ako je ovo bio zadnji posao, pusti sve dretve koje su
  342.  
  343. �ekale na kraj slova */
  344.  
  345. if ( dretve->br_poslova == 0 )
  346.  
  347. pthread_cond_broadcast ( &dretve->gotovo );
  348.  
  349. }
  350.  
  351. else { /* nema poslova pa �ekaj */
  352.  
  353. pthread_cond_wait ( &dretve->red, &dretve->brava );
  354.  
  355. }
  356.  
  357. }
  358.  
  359. pthread_mutex_unlock ( &dretve->brava );
  360.  
  361. return NULL; /* završetak radne dretve */
  362.  
  363. }
  364.  
  365. /*!
  366.  
  367. * Dodaje posao skupu dretvi
  368.  
  369. * \param dretve Opisnik skupa dretvi
  370.  
  371. * \param funkcija Kazaljka na funkciju koja obavlja posao
  372.  
  373. opcionalni parametri posla:
  374.  
  375. * \param pparam Prvi parametar funkcije (kazaljka, može biti NULL)
  376.  
  377. * \param iparam Drugi parametar funkcije (cijeli broj)
  378.  
  379. */
  380.  
  381. void dodaj_posao ( void *dretve, void *funkcija, void *pparam, int iparam )
  382.  
  383. {
  384.  
  385. posao_t *posao;
  386.  
  387. radne_dretve_t *skup;
  388.  
  389. static unsigned int zadnji_broj = 1; /* za dodjelu ID poslu */
  390.  
  391. posao = malloc ( sizeof (posao_t) );
  392.  
  393. posao->id = zadnji_broj++;
  394.  
  395. posao->funkcija = funkcija;
  396.  
  397. posao->pparam = pparam;
  398.  
  399. posao->iparam = iparam;
  400.  
  401. skup = dretve;
  402.  
  403. /* dodaj posao u red poslova unutar skupa dretvi */
  404.  
  405. pthread_mutex_lock ( &skup->brava );
  406.  
  407. if ( skup->zadnji == NULL )
  408.  
  409. skup->prvi = posao;
  410.  
  411. else
  412.  
  413. skup->zadnji->iduci = posao;
  414.  
  415. skup->zadnji = posao;
  416.  
  417. posao->iduci = NULL;
  418.  
  419. skup->br_poslova++;
  420.  
  421. pthread_mutex_unlock ( &skup->brava );
  422.  
  423. /* signaliziraj radnim dretvama da se pojavio novi posao */
  424.  
  425. pthread_cond_signal ( &skup->red );
  426.  
  427. }
  428.  
  429. /*!
  430.  
  431. * Blokira pozivajucu (glavnu) dretvu dok svi poslovi iz skupa dretvi ne budu
  432.  
  433. * gotovi
  434.  
  435. * \param dretve Opisnik skupa dretvi
  436.  
  437. * \param cekaj Oznaka da li blokirati (cekaj != 0) ili ne (cekaj == 0)
  438.  
  439. * pozivajucu dretvu, ako poslovi jos nisu gotovi
  440.  
  441. * \returns status, 0 ako su poslovi dovrseni, 1 inace (kada je cekaj == 0)
  442.  
  443. */
  444.  
  445. int cekaj_dovrsetak_poslova ( void *dretve, int cekaj ){
  446.  
  447. radne_dretve_t *thread;
  448.  
  449. thread=dretve;
  450.  
  451. if(cekaj!=0){
  452.  
  453. pthread_mutex_lock(&thread->brava);
  454.  
  455. if(thread->prvi!=NULL){
  456.  
  457. pthread_cond_wait(&thread->gotovo, &thread->brava);
  458.  
  459. }
  460.  
  461. pthread_mutex_unlock(&thread->brava);
  462.  
  463. }else{
  464.  
  465. if(thread->prvi!=NULL){
  466.  
  467. return 1;
  468.  
  469. }
  470.  
  471. }
  472.  
  473. return 0;
  474.  
  475. }
  476.  
  477.  
  478.  
  479. int makni_radne_dretve ( void *dretve ){
  480.  
  481. int i;
  482.  
  483. radne_dretve_t *skup;
  484.  
  485. skup = dretve;
  486.  
  487. skup->kraj = 1;
  488.  
  489.  
  490.  
  491. pthread_cond_broadcast ( &skup->red );
  492.  
  493. for( i = 0; i<skup->broj; i++){
  494.  
  495. pthread_join ( skup->iddr[i], NULL );
  496.  
  497. }
  498.  
  499.  
  500.  
  501. pthread_mutex_lock ( &rd_brava );
  502.  
  503.  
  504.  
  505. while ( rd_prvi != NULL){
  506.  
  507. skup = rd_prvi->iduci;
  508.  
  509. free ( rd_prvi );
  510.  
  511. rd_prvi = skup;
  512.  
  513. }
  514.  
  515.  
  516.  
  517. free ( skup );
  518.  
  519. pthread_mutex_unlock ( &rd_brava );
  520.  
  521.  
  522.  
  523. return 0;
  524.  
  525. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement