2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Säie: Prosessin entiteetti ja suorittimen ajoituksen ja lähettämisen perusyksikkö. Säike itsessään ei periaatteessa omista järjestelmäresursseja, vain muutamia resursseja, jotka ovat välttämättömiä toiminnan kannalta (kuten ohjelmalaskuri, joukko rekistereitä ja pino), mutta se voi jakaa kaikki prosessin omistamat resurssit muiden säikeiden kanssa. jotka kuuluvat samaan prosessiin. Säie voi luoda ja tuhota useita säikeitä samassa prosessissa. Langat osoittavat ajoittaista käyttäytymistä käytön aikana. (Yllä oleva on "Tietokonetason 4 opetusohjelmasta - Käyttöjärjestelmän periaatteet")
Säikeistä puhuttaessa on tarpeen puhua prosessin määrittelystä: prosessi on ohjelma, jolla on tietyt itsenäiset toiminnot. Prosessi on itsenäinen yksikkö resurssien allokoinnille ja aikataululle. (Yllä oleva on "Tietokonetason 4 opetusohjelmasta - Käyttöjärjestelmän periaatteet")
Prosessin määritelmä on hieman mutkikas. Katsotaanpa, mistä prosessi koostuu: ohjelmasta, tiedosta ja prosessin ohjauslohkosta. Niistä ohjelma vastaa prosessimääritelmässä "ohjelmaa, jolla on tietyt itsenäiset toiminnot". Prosessi tarvitsee itse ohjelman lisäksi myös dataa (jotka voidaan ymmärtää resursseina) ja prosessin ohjauslohkoja. Tietojen ja prosessien ohjauslohkot ovat olennaisia resursseja ohjelman ollessa käynnissä Ohjelma luottaa näihin resursseihin vastaavien toimintojen suorittamisessa, jota kutsumme "prosessiksi".
Prosessien kaksi perusominaisuutta:
Prosessi on itsenäinen yksikkö, joka voi omistaa resursseja;
Prosessi on perusyksikkö, joka voidaan ajastaa ja lähettää itsenäisesti.
Kun säikeet perustettiin, oli tarkoitus erottaa prosessin kaksi edellä mainittua attribuuttia. Säikeet muodostavat "CPU:n ajoituksen ja lähettämisen perusyksikön". Tällä tavalla prosessissa voi olla monia säikeitä ja lähettää säikeitä paremmin Se voi toteuttaa prosessien rinnakkaissuorittamisen samaan aikaan, samaan prosessiin kuuluvat säikeet voivat jakaa kaikki prosessin resurssit, mikä voi tyydyttää eri säikeiden pääsyn prosessiresursseihin samassa prosessissa. Säikeiden syntyminen erottaa nerokkaasti prosessin kaksi attribuuttia, jolloin prosessi pystyy paremmin käsittelemään rinnakkaissuorituksen tarpeita.
Lanka on käynnissä oleva toiminto. POSIX-säikeet ovat joukko standardeja, eivät joukko toteutuksia. On olemassa muita standardeja, kuten: openmp-säikeet.
Säikeen tunniste: pthread_t (en tiedä tarkkaa sisältöä, jokainen yritys toteuttaa sen eri tavalla, Linuxissa se on int)
px axm -komento näkee prosessit ja säikeet, jotka edustavat prosessin alaisia säikeitä. px ax -L tarkastellaksesi kevyitä lankoja.
int pthread_equal(pthread_t t1, pthread_t t2) Vertaa kahden säikeen tunnusnumeroita. Jos ne ovat samat, palautetaan nollasta poikkeava, jos ne ovat erilaisia, palautetaan 0.
pthread_t pthread_self(void);
int pthread_create(pthread_t *säie, const pthread_attr_t *attr,
void *(*aloitus_rutiini) (void *), void *arg);
Säikeen ajoitus riippuu ajoittajan strategiasta.
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- printf("thread %ld n",pthread_self());
- return NULL;
- }
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- printf("main %ld n",pthread_self());
-
-
-
- puts("End!");
- }
1. Säie palaa käynnistysrutiinista, ja palautusarvo on säikeen poistumiskoodi.
2. Saman prosessin muut säikeet voivat peruuttaa säikeet.
3. Säie kutsuu pthread_exit()-funktiota. void pthread_exit(void *retval);
int pthread_join(pthread_t säie, void **retval) Se vastaa prosessin odotusta ja sitä käytetään ruumiiden keräämiseen.
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- pthread_exit(NULL);//线程专用清理函数。
- // return NULL;
- }
-
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- pthread_join(tid,NULL); //收尸
-
- puts("End!");
- }
pthread_cleanup_push(); //Vastaa kuin atexit
pthread_cleanup_pop(); //Vastaa tietojen aktiivista hakemista.
void pthread_cleanup_push(void (*rutiini)(void *), on makron gcc -E toteutus esikäsittelyn katseluun
void *arg);
void pthread_cleanup_pop(int execute) //Valitse kutsutaanko.On näytettävä pareittain makroilla toteutettuna
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
-
- void cleanup_fun(void*p)
- {
- puts(p);
- }
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- pthread_cleanup_push(cleanup_fun,"cleanup:1");
- pthread_cleanup_push(cleanup_fun,"cleanup:2");
- pthread_cleanup_push(cleanup_fun,"cleanup:3");
-
- puts("push over!");
-
-
-
- pthread_exit(NULL);//线程专用清理函数。
- // return NULL;
- pthread_cleanup_pop(1) //线程退出后,全部都会调用;
- pthread_cleanup_pop(0);
- pthread_cleanup_pop(1);
- }
-
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- pthread_join(tid,NULL); //收尸
-
- puts("End!");
- }
Jos käynnissä oleva säie haluaa kerätä ruumiin, sen on ensin peruutettava (pthread_cancel) ja sitten kerättävä ruumis (pthread_join).
Säikeen peruutus: int pthread_cancel(pthread_t säie);
Peruutuksella on kaksi tilaa: sallittu ja ei sallittu.
Peruutus ei ole sallittu: koodin suoritus jatkuu ennallaan.
Sallittu peruutus jaetaan: asynkroninen peruutus ja viivästetty peruutus (oletus) -> viivästetty vastaus peruutuskohtaan asti.
Cancal point: Posixin määrittämät peruutuspisteet ovat järjestelmäkutsuja, jotka voivat aiheuttaa ruuhkaa.
pthread_setcancelstate: Peruutustila voidaan asettaa.
pthread_setcanceltype: Voit määrittää peruutustavan.
pthread_testcancel: Funktio ei tee mitään, vain peruuttaa pisteen.
Säikeen irrotus: int pthread_detach(pthread_t säie);
Dynaamisen moduulin yksi alustustoiminto: int pthread_once(pthread_once_t *once_control,
void (*aloitus_rutiini)(void));
pthread_once_t Once_control = PTHREAD_ONCE_INIT;
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
Kilpailua käydään, kun yllä oleva koodi suoritetaan. Koska parametrit välitetään osoitteen mukaan, tiedot on haettava merkillä *, eikä ole takeita siitä, onko edellinen säie suorittanut toiminnon. Yksinkertaisin tapa on käyttää arvon välitystä.
primer0.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
primer0_e.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- struct thr_arg_st
- {
- int n;
- };
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- struct thr_arg_st* p;
- void *ptr;
- for(i =LEFT;i<=RIGHT;i++)
- {
- p = malloc(sizeof(*p));
- if(p ==NULL)
- {
- perror("malloc");
- exit(1);
- }
- p->n = i;
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,p); // p就是结构体指针就是n的地址
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- //free 不能在这里free,必须取走数据在free
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],&ptr);// 收尸并且接受返回参数。
- free(ptr);
-
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = ((struct thr_arg_st*)p)->n;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(p); //返回值返回p
- return NULL;
- }
add.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (20)
-
- void* thr_add(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<=THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_add,NULL);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=0;i<=THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
-
- return 0;
- }
-
- void* thr_add(void*p)
- {
- FILE*fp;
- char line_buf[1024];
- int len_size = 1024;
- fp = fopen(FILENAME,"r+");
-
- fgets(line_buf,len_size,fp);
-
- fseek(fp,0,SEEK_SET);
-
- fprintf(fp,"%d n",atoi(line_buf)+1);
-
- fclose(fp);
-
- pthread_exit(NULL);
-
- return NULL;
- }
Kilpailua ja ristiriitoja voi esiintyä, kun kaksikymmentä säiettä lukee ja kirjoittaa tietoja tiedostoon samanaikaisesti. Ennen kuin yksi säie kirjoittaa sisään, toinen säie lukee viimeiset tiedot.
- #include <stdlib.h>
- #include <stdio.h>
- #include <error.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <signal.h>
- #include <pthread.h>
-
- #include "mytbf.h"
-
- struct mytbf_st
- {
- int cps;
- int burst;
- int token;
- int pos;
- pthread_mutex_t mut;
- };
- static pthread_mutex_t mut_job = PTHREAD_MUTEX_INITIALIZER;
- static pthread_t tid_alrm;
- pthread_once_t init_once = PTHREAD_ONCE_INIT;
-
- static struct mytbf_st* job[MYTBF_MAX];
-
- typedef void (*sighandler_t)(int);
-
-
- static int get_free_pos_unlocked(void)
- {
- for(int i=0;i< MYTBF_MAX;i++)
- {
- if(job[i]==NULL)
- return i;
- }
- return -1;
- }
-
- static void* thr_alrm(void*p)
- {
- while(1)
- {
- pthread_mutex_lock(&mut_job);
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i] != NULL)
- {
- pthread_mutex_lock(&job[i]->mut);
- job[i]->token += job[i]->cps;
- if(job[i]->token >job[i]->burst )
- {
- job[i]->token = job[i]->burst;
- }
- pthread_mutex_unlock(&job[i]->mut);
- }
- }
- pthread_mutex_unlock(&mut_job);
- sleep(1);
- }
- return NULL;
- }
-
- static void module_unload()
- {
- pthread_cancel(tid_alrm);
- pthread_join(tid_alrm,NULL);
- //只能一个人掉,二个人调用容易出差
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i]!=NULL)
- {
- mytbf_destroy(job[i]);
- }
- }
- pthread_mutex_destroy(&mut_job);
-
- }
-
- static void module_load()
- {
- int err;
- err = pthread_create(&tid_alrm,NULL,thr_alrm,NULL);
- if(err)
- {
- fprintf(stderr,"create errorn");
- exit(1);
- }
- atexit(module_unload);
- }
-
- mytbf_t* mytbf_init(int cps ,int burst) //C语言中,void*可以赋值给任何类型的指针,任何类型的指针也都可以赋值给void*
- {
- struct mytbf_st*me;
- int pos;
- pthread_once(&init_once,module_load); //只初始化一次
- me = malloc(sizeof(*me));
- if(me == NULL)
- return NULL;
-
- me->cps = cps;
- me->burst = burst;
- me->token = 0;
-
- pthread_mutex_init(&me->mut,NULL);
-
- pthread_mutex_lock(&mut_job);
-
- pos = get_free_pos_unlocked();
- if(pos < 0)
- {
-
- pthread_mutex_unlock(&mut_job);
- free(me);
- return NULL;
- }
- me->pos = pos;
- job[pos] = me;
-
- pthread_mutex_unlock(&mut_job);
-
- return me;
-
- }
- int mytbf_fetchtoken(mytbf_t*ptr,int size) //获取token
- {
- if(size <= 0)
- return -EINVAL; //参数非法
- struct mytbf_st*me = ptr;
- pthread_mutex_lock(&me->mut);
- while(me->token <= 0 ) //token为空就等待
- {
- pthread_mutex_unlock(&me->mut);
- sched_yield();
- pthread_mutex_lock(&me->mut);
- }
-
- int n = (me->token>size?size:me->token);
- me->token -= n;
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- int mytbf_returntoken(mytbf_t*ptr,int size) //返还token
- {
- if(size<=0)
- return -EINVAL;
- struct mytbf_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->token+= size;
- if(me->token > me->burst)
- me->token = me->burst;
-
- pthread_mutex_unlock(&me->mut);
- return size;
- }
-
- int mytbf_destroy(mytbf_t*ptr)
- {
- struct mytbf_st *me;
- me = ptr;
- pthread_mutex_lock(&mut_job);
- job[me->pos] = NULL;
- pthread_mutex_unlock(&mut_job);
- pthread_mutex_destroy(&me->mut);
- free(ptr);
- return 0;
-
- }
Se vastaa lukkoa, joka on avattava ennen kuin sitä voidaan käyttää. (kyselymenetelmä)
Jos man pthread_mutex_init ilmoittaa virheestä, asenna riippuvuudet:
sudo apt-get install manpages-posix manpages-posix-dev
int pthread_mutex_destroy(pthread_mutex_t *mutex); //Tuhoa lukko
int pthread_mutex_init(pthread_mutex_t *rajoita mutex,
const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER staattinen alustus
int pthread_mutex_lock(pthread_mutex_t *mutex); //加锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);//Yritä lukita, jos ei, jatka suoritusta
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
add.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (20)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-
- void* thr_add(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_add,NULL);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
-
- void* thr_add(void*p)
- {
- FILE*fp;
- char line_buf[1024];
- int len_size = 1024;
-
- pthread_mutex_lock(&mut);
-
-
- fp = fopen(FILENAME,"r+");
- fgets(line_buf,len_size,fp);
-
- fseek(fp,0,SEEK_SET);
-
- fprintf(fp,"%d n",atoi(line_buf)+1);
- fclose(fp);
- pthread_mutex_unlock(&mut);
-
- pthread_exit(NULL);
-
- return NULL;
- }
abcd.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
-
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- while(1)
- {
- write(1,&c,1);
- }
-
- pthread_exit(NULL);
-
- return NULL;
- }
abcd.c
Käytä ketjua lukitsemiseen ja avaamiseen.
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut[THRNUM];
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- pthread_mutex_init(mut+i,NULL); //初始化四个锁
- pthread_mutex_lock(mut+i);
-
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- pthread_mutex_unlock(mut+0);
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
- int next(int n)
- {
- if(n +1 ==THRNUM)
- return 0;
- return n+1;
- }
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- int n = (int)p;
- while(1)
- {
- pthread_mutex_lock(mut+n);
- write(1,&c,1);
- pthread_mutex_unlock(mut+next(n) );
- }
- pthread_exit(NULL);
-
- return NULL;
- }
Pool-algoritmi toteuttaa alkulukulaskelman (kyselymenetelmä)
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
Ilmoituslaki viestintää varten.
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *rajoita attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);//Herätä kaikki odotukset
int pthread_cond_timedwait(pthread_cond_t *restrict cond, //timeout odota
pthread_mutex_t *rajoita mutex,
const struct timepec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond, //死等
pthread_mutex_t *rajoita mutex);
mytbf.c (ilmoitustapa)
- #include <stdlib.h>
- #include <stdio.h>
- #include <error.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <signal.h>
- #include <pthread.h>
-
- #include "mytbf.h"
-
- struct mytbf_st
- {
- int cps;
- int burst;
- int token;
- int pos;
- pthread_mutex_t mut;
- pthread_cond_t cond;
-
- };
- static pthread_mutex_t mut_job = PTHREAD_MUTEX_INITIALIZER;
- static pthread_t tid_alrm;
- pthread_once_t init_once = PTHREAD_ONCE_INIT;
-
- static struct mytbf_st* job[MYTBF_MAX];
-
- typedef void (*sighandler_t)(int);
-
-
- static int get_free_pos_unlocked(void)
- {
- for(int i=0;i< MYTBF_MAX;i++)
- {
- if(job[i]==NULL)
- return i;
- }
- return -1;
- }
-
- static void* thr_alrm(void*p)
- {
- while(1)
- {
- pthread_mutex_lock(&mut_job);
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i] != NULL)
- {
- pthread_mutex_lock(&job[i]->mut);
- job[i]->token += job[i]->cps;
- if(job[i]->token >job[i]->burst )
- {
- job[i]->token = job[i]->burst;
- }
- pthread_cond_broadcast(&job[i]->cond);
- pthread_mutex_unlock(&job[i]->mut);
- }
- }
- pthread_mutex_unlock(&mut_job);
- sleep(1);
- }
- return NULL;
- }
-
- static void module_unload()
- {
- pthread_cancel(tid_alrm);
- pthread_join(tid_alrm,NULL);
- //只能一个人掉,二个人调用容易出差
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i]!=NULL)
- {
- mytbf_destroy(job[i]);
- }
- }
- pthread_mutex_destroy(&mut_job);
-
- }
-
- static void module_load()
- {
- int err;
- err = pthread_create(&tid_alrm,NULL,thr_alrm,NULL);
- if(err)
- {
- fprintf(stderr,"create errorn");
- exit(1);
- }
- atexit(module_unload);
- }
-
- mytbf_t* mytbf_init(int cps ,int burst) //C语言中,void*可以赋值给任何类型的指针,任何类型的指针也都可以赋值给void*
- {
- struct mytbf_st*me;
- int pos;
- pthread_once(&init_once,module_load); //只初始化一次
- me = malloc(sizeof(*me));
- if(me == NULL)
- return NULL;
-
- me->cps = cps;
- me->burst = burst;
- me->token = 0;
-
- pthread_mutex_init(&me->mut,NULL);
- pthread_cond_init(&me->cond,NULL);
- pthread_mutex_lock(&mut_job);
-
- pos = get_free_pos_unlocked();
- if(pos < 0)
- {
-
- pthread_mutex_unlock(&mut_job);
- free(me);
- return NULL;
- }
- me->pos = pos;
- job[pos] = me;
-
- pthread_mutex_unlock(&mut_job);
-
- return me;
-
- }
- int mytbf_fetchtoken(mytbf_t*ptr,int size) //获取token
- {
- if(size <= 0)
- return -EINVAL; //参数非法
- struct mytbf_st*me = ptr;
- pthread_mutex_lock(&me->mut);
- while(me->token <= 0 ) //token为空就等待
- {
- pthread_cond_wait(&me->cond,&me->mut); //解锁等待,等待conad_broadcast和conad_signal的到来
-
- /*
- pthread_mutex_unlock(&me->mut);
- sched_yield();
- pthread_mutex_lock(&me->mut);
- */
- }
-
-
- int n = (me->token>size?size:me->token);
- me->token -= n;
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- int mytbf_returntoken(mytbf_t*ptr,int size) //返还token
- {
- if(size<=0)
- return -EINVAL;
- struct mytbf_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->token+= size;
- if(me->token > me->burst)
- me->token = me->burst;
- pthread_cond_broadcast(&me->cond);
- pthread_mutex_unlock(&me->mut);
- return size;
- }
-
- int mytbf_destroy(mytbf_t*ptr)
- {
- struct mytbf_st *me;
- me = ptr;
- pthread_mutex_lock(&mut_job);
- job[me->pos] = NULL;
- pthread_mutex_unlock(&mut_job);
- pthread_mutex_destroy(&me->mut);
- pthread_cond_destroy(&me->cond);
- free(ptr);
- return 0;
-
- }
primer0_pool.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #include <sched.h>
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (4)
-
- static int num = 0;
- static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
- static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
-
- for(i =0;i<=THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_prime,(void *)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- //下发任务
- for(i=LEFT;i<RIGHT;i++)
- {
- pthread_mutex_lock(&mut);
- while(num !=0) //不是0就需要等待任务被取走
- {
- pthread_cond_wait(&cond,&mut);
- }
-
- num = i; //下发任务
- pthread_cond_signal(&cond); //下游叫醒任意一个
- pthread_mutex_unlock(&mut);
- }
- pthread_mutex_lock(&mut);
- while(num!= 0)
- {
- pthread_mutex_unlock(&mut);
- sched_yield(); //出让调度器给别的线程
- }
- num = -1; //用于线程退出
- pthread_cond_broadcast(&cond);
-
- pthread_mutex_unlock(&mut);
-
- for(i=0;i<=THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- pthread_cond_destroy(&cond);
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
- while(1)
- {
- pthread_mutex_lock(&mut);
- while(num == 0)
- {
- pthread_cond_wait(&cond,&mut);
- }
- if(num == -1)
- {
- pthread_mutex_unlock(&mut); //走到这里必须要解锁。
- break;
- }
-
- i= num;
- num = 0;
- pthread_cond_broadcast(&cond);
-
- pthread_mutex_unlock(&mut);
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("[%d]%d is a primer n",(int)p,i);
- }
-
- pthread_exit(NULL);
- return NULL;
- }
abcd_cond.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
- pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
- int num;
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
-
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_cond_destroy(&cond);
- pthread_mutex_destroy(&mut);
- return 0;
- }
- int next(int n)
- {
- if(n +1 ==THRNUM)
- return 0;
- return n+1;
- }
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- int n = (int)p;
- while(1)
- {
- pthread_mutex_lock(&mut);
- while(num != n)
- {
- pthread_cond_wait(&cond,&mut);
- }
- write(1,&c,1);
- num = next(num);
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mut );
- }
- pthread_exit(NULL);
-
- return NULL;
- }
Mutex on tyyppiä bool ja semafori on tyyppiä int. Jos se ei riitä, se odottaa.
mysem.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
- #include <unistd.h>
- #include "mysem.h"
-
- struct mysem_st
- {
- int value;
- pthread_mutex_t mut;
- pthread_cond_t cond;
-
- };
-
- mysem_t* mysem_init(int initval)
- {
- struct mysem_st*me;
- me = malloc(sizeof(*me));
- if(me==NULL)
- return NULL;
- me->value = initval;
- pthread_mutex_init(&me->mut,NULL);
- pthread_cond_init(&me->cond,NULL);
-
- return me;
-
- }
-
- int mysem_add(mysem_t*ptr ,int n)
- {
- struct mysem_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->value+= n;
- pthread_cond_broadcast(&me->cond);
- pthread_mutex_unlock(&me->mut);
-
- return n;
- }
-
- int mysem_sub(mysem_t*ptr ,int n )
- {
- struct mysem_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
- while(me->value <n)
- {
- pthread_cond_wait(&me->cond,&me->mut);
- }
- me->value -=n;
-
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- void mysem_destroy(mysem_t*ptr)
- {
- struct mysem_st*me = ptr;
- pthread_mutex_destroy(&me->mut);
- pthread_cond_destroy(&me->cond);
- free(me);
- }
-
-
-
mysem.h
- #ifndef MYSEM_H
- #define MYSEM_H
-
- typedef void mysem_t;
-
- mysem_t* mysem_init(int initval);
-
- int mysem_add(mysem_t*,int);
-
- int mysem_sub(mysem_t*,int);
-
- void mysem_destroy(mysem_t*);
-
-
-
- #endif
main.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #include "mysem.h"
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- #define N 4
- static mysem_t* sem;
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
-
- sem = mysem_init(N);
- if(sem ==NULL)
- {
- fprintf(stderr,"mysem_init n");
- exit(1);
- }
-
- for(i =LEFT;i<=RIGHT;i++)
- {
- mysem_sub(sem,1);
-
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- mysem_destroy(sem);
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
-
- sleep(5); //ps ax -L 可以观察到对线程进行了限制,只创建了四个线程
-
- mysem_add(sem,1);
- pthread_exit(NULL);
-
- return NULL;
- }
makefile
- all:mysem
- CFLAGS+=-g -Wall -pthread
- LDFLAGS+= -pthread
-
- mysem:main.o mysem.o
- gcc $^ $(CFLAGS) $(LDFLAGS) -o $@
-
- clean:
- rm -rf *.o mysem
Mutexien ja semaforien kattava käyttö. Jaettu lukulukkoon (semafori) ja kirjoituslukkoon (mutex). Yleensä lukemiselle ja kirjoittamiselle tulisi asettaa yläraja.
On välttämätöntä estää kirjailijoiden kuolema nälkään.
Pthread_create-parametrin toinen parametri on säikeen attribuutti.
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
Testiohjelman luomien säikeiden enimmäismäärä. ()
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
-
- void* func(void)
- {
- int i;
-
- // printf("%pn",&i);
- pthread_exit(NULL);
- return NULL;
- }
-
- int main()
- {
- int err;
- pthread_t tid;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr,1024*1024); //1mb
-
- int i = 0;
- for(;;i++)
- {
- err = pthread_create(&tid,&attr,func,NULL);
- if(err)
- {
- fprintf(stderr,"create errn");
- break;
- }
- }
- printf("max = %d n",i);
- pthread_attr_destroy(&attr);
- return 0;
- }
Mutex-ominaisuudet:
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
Katso pthread_mutexattr_destroy().
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, //toimii prosesseissa
int *pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
int pshared);
//Luo aliprosessi, joka voi jakaa tiedostokuvaustaulukon. Voit myös olla jakamatta sitä. Prosessien ja säikeiden välillä ei ole eroa Linuxissa
int clone(int (*fn)(void *), void *pino, int liput, void *arg, ...
/* pid_t *parent_tid, void *tls, pid_t *child_tid */ );
int pthread_mutexattr_gettype(const pthread_mutexattr_t *rajoita attr,
int *rajoitustyyppi);
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int tyyppi);
Ehtomuuttujan ominaisuudet:
int pthread_condattr_destroy(pthread_condattr_t *attr);
int pthread_condattr_init(pthread_condattr_t *attr);
Luku-kirjoituslukon ominaisuudet:
Reentrant-toiminto on yksinkertaisesti toiminto, joka voidaan keskeyttää. Voit siis keskeyttää tämän toiminnon milloin tahansa sen suorittamisen aikana ja siirtää toisen koodinpalautuksen ilman virheitä funktiot käyttävät joitain järjestelmäresursseja, kuten globaaleja muuttujaalueita, keskeytysvektoritaulukoita jne., joten jos ne keskeytyvät, tällaisia toimintoja ei voi suorittaa moniajoympäristössä.
IO monisäikeisessä. Avattu toiminto päättyy (ei-reentrant-toiminto, monisäikeistä samanaikaisuutta ei tueta). man putc_unlocked, katso ei-tuetut IO-toiminnot.
int pthread_sigmask(int miten, const sigset_t *joukko, sigset_t *vanha joukko);
int sigwait(const sigset_t *set, int *sig);
int pthread_kill(pthread_t säie, int sig);
Katso virallinen verkkosivusto: www.OpenMp.org
Openmp-syntaksitunnisteita tuetaan gcc4.0:n jälkeen.Kuinka monta samanaikaisuutta voidaan saavuttaa muutamalla prosessorilla?
hei C
- #include <stdio.h>
- #include <stdlib.h>
-
- int main()
- {
- #pragma omp parallel //实现并发
- {
- puts("Hello ");
- puts(" World");
- }
- return 0;
- }
makefile
CFLAGS += -Wall -fopenmp
Kääntää make hello ja ajaa se.
- #include <stdio.h>
- #include <stdlib.h>
- #include <omp.h>
-
- int main()
- {
- #pragma omp parallel sections
- {
- #pragma omp section
- printf("[%d:]Hello n",omp_get_thread_num() );
- #pragma omp section
- printf("[%d:]World n",omp_get_thread_num() );
- }
- return 0;
- }