در توسینسو تدریس کنید

و

با دانش خود درآمد کسب کنید

کار با threadها در لینوکس - قسمت دوم

3. اولین استفاده از threadها


در حال حاضر مجموعه ی کاملی از فراخوانی های کتابخانه ای مرتبط با نخ ها وجود دارد که که نام بیشتر آن ها با pthread شروع می شود. برای استفاده ار این فراخوانی های کتابخانه ای، باید ابتدا ماکروی REENTRANT_ را تعریف کنیم، سپس فایل pthread.h را ضمیمه کرده و با کتابخانه ی نخ ها با استفاده از lpthread- یک پیوند برقرار کنیم.

وقتی روتین های کتابخانه ای ابتدایی POSIX و UNIX طراحی می شد، اینطور در نظر گرفته شد که فقط یک تک نخ اجرایی درون هر پردازه وجود دارد. یک مثال واضح errno است. از این متغیر برای بازیابی اطلاعات خطا بعد از به شکست انجامیدن یک فراخوانی استفاده می شود. در یک برنامه چند نخه به طور پیش فرض یک متغیر errno وجود دارد که بین همه ی نخ ها به اشتراک گذاشته شده است. قبل از اینکه یک نخ قادر به بازیابی اطلاعات خطا از این منتغیر باشد، نخ دیگر می تواند به راحتی محتویات این متغیر را بروز رسانی کند (در نتیجه اطلاعات آن را از بین ببرد). توابعی مانند fputs نیز چنین مشکلاتی را دارند. این تابع به طور نرمال از یک فضای عمومی برای بافر کردن خروجی استفاده می کند.

شما به روتین های خاصی به نام روتین های re-entrant نیاز دارید. کد Re-entrant را می توانیم چه به وسیله ی نخ های متفاوت و چه از طریق فراخوانی های تو در تو، چندین بار فراخوانی کنیم به گونه ای که مشکلی پیش نیاید و عملکرد درستی را شاهد باشیم. با این وجود بخش بازگشتی کد معمولا باید از متغیرهای محلی تنها به طریقی استفاده کند که هر فراخونی، کپیِ یکتای مخصوص به خودش را از داده ها به دست آورد. (reentrant : روالى که مى تواند توسط چندين برنامه مستقل بطور همزمان بکار برده شود).

در برنامه های چند نخی، شما با تعریف ماکروی REENTRANT_ قبل از هر یک از خطوط include# درون برنامه، به کامپایلر می گویید که به این ویژگی نیاز دارید. این کار سبب رخ دادن سه چیز می شود:

  • نمونه های امن بازگشتی برای بعضی از توابع به دست می آید. نام این توابع به صورت قبل است، با این تفاوت که r- به آنها اضافه می شود. مثلا تابع gethostbyname به صورت gethostbyname_r تغییر می کند.
  • بعضی ار توابع stdio.h که در حالت نرمال به صورت ماکرو پیاده سازی شده اند، تبدیل به توابع امن بازگشتی مناسبی می شوند.
  • متغیر errno از فایل errno.h به گونه ای تغییر می کند که یک تابع را صدا بزند. این تابع قادر است به طریقی امن، مقدار واقعی errno را در یک برنامه ی چند نخی تعیین کند.

ضمیمه کردن فایل pthread.h برای شما تعاریف و نمونه های دیگری را فراهم می کند که در کد برنامه به آن ها نیاز پیدا خواهید کرد؛ بسیار شبیه به stdio.h برای روتین های استاندارد ورودی و خروجی. در پایان شما باید مطمئن شوید که فایل های سرآیند مناسبی را برای کار با نخ ها ضمیمه کرده اید و همچنین با کتابخانه نخ مناسبی که توابع pthread.h را پیاده سازی می کنند، پیوند برقرار کرده اید.

در ادامه به معرفی توابع پایه ای برای مدیریت نخ ها می پردازیم.

تابع pthread_create

تابع pthread_create مثل تابع fork که یک فرآیند جدید را ایجاد می کند، سبب به وجود آمدن یک نخ جدید می شود.

#include <pthread.h>
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

اولین آرگومان یک اشاره گر به pthread_t می باشد. شناسه نخ به وجود آمده درون حافظه ای که این آرگومان به آن اشاره می کند نوشته می شود. به وسیله این شناسه می توانید به نخ رجوع کنید.

دومین آرگومان صفات نخ را تنظیم می کند. معمولا نیازی به تعیین صفت خاصی برای نخ نیست، به همین دلیل به جای این آرکومان می توانید مقدار NULL را بفرستید.

سومین و چهارمین آرگومان به ترتیب تابع و آرگومان های تابعی است که نخ باید شروع به اجرای آن کند.

void (start_routine)(void *)

خط قبل می گوید که شما باید آدرس یک تابع را ارسال کنید که یک اشاره گر به void را به عنوان پارامتر گرفته و تابع یک اشاره گر به void را برمی گرداند. شما می توانید هر نوعی را به عنوان آرگومان فرستاده و اشاره گری به هر نوع دلخواه را برگردانید.

در صورت موفقیت، مقدار بازگشتی این تابع 0 می باشد. در صورت بروز مشکل شماره های دیگری برگردانده می شود.

تابع pthread_create مانند بسیاری از توابع pthread-، جز محدود توابع لینوکس هستند که از قرارداد بازگرداندن مقدار 1 در صورت برورز خطا پیروی نمی کند. با این وجود بهتر است که همیشه صفحات راهنما را برای آگاهی از مقادیر بازگشتی بررسی کنیم.

تابع pthread_exit

وقتی یک نخ خاتمه پیدا می کند، تابع pthread_exit را صدا می زند، درست مثل پردازه ها که به هنگام خاتمه تابع exit را فراخوانی می کنند. این تابع نخ را خاتمه می دهد و یک اشاره گر به یک شی را برمی گرداند. هیچ وقت از این برای برگرداندن یک اشاره گر به یک متغیر محلی استفاده نکنید، زیرا متغیرهای محلی در صورت از بین رفتن نخ ها دیگر وجود نخواهند داشت و همین سبب به وجود آمدن باگ های جدی خواهند شد. pthread-exit به صورت زیر اعلان می شود:

#include <pthread.h>
void pthread_exit(void *retval);

تابع pthread_join

تابع دیگری که به معرفی آن می پردازیم تابع pthread_join است. کار این تابع مانند تابع wait می باشد. همانطور که می دانید در صورت استفاده از تابع wait، پردازه والد در انتظار خاتمه پردازه های فرزند می ماند. این تابع به صورت زیر اعلان می شود:

#include <pthread.h>
int pthread_join(pthread_t th, void **thread_return);

اولین آرگومان شناسه نخی است که باید برای آن صبر کنیم.

دومین آرگومان اشاره گری به یک اشاره گر است که خود به مقدار بازگشتی نخ اشاره می کند. (به زبان ساده، مقدار بازگشتی نخ، یعنی همان مقداری که توسط تابع pthread_exit مشخص می شود، درون این آرگومان قرار می گیرد).

مثل تابع pthread_create این تابع نیز در صورت موفقیت مقدار 0 و در صورت شکست کد خطای دیگری را برمی گرداند.

در ادامه با یک مثال، نحوه به کارگیری توابع ذکر شده در بالا را نشان می دهیم.

#include "stdlib.h"
#include "stdio.h"
#include "unistd.h"
#include "string.h"
#include "pthread.h"

void *MyThreadFunc(void *args){
	printf("from thread:: thread is running.....\nfrom thread:: function args: %s\n",(char *)args);
	srand(time(NULL));
	int rnd=rand()%6;
	sleep(rnd);
	printf("from thread:: thread execution lasts %d second(s)\n",rnd);
	pthread_exit("good by world");
}

void main(){
	pthread_t thread_id;
	void *thread_result;
	if(pthread_create(&thread_id,NULL,MyThreadFunc,"Hello World")==0){
		printf("from main:: waiting for thread %d  .....\n\n",thread_id);
		if(pthread_join(thread_id,&thread_result)==0){
			printf("\nfrom main:: thread return value: %s\n",(char *)thread_result);
		}
	}
}

به فرض اینکه نام برنامه thread1 باشد، برای کامپایل آن باید به صورت زیر عمل کنیم:

cc -D_REENTRANT thread1.c -o thread1

نمونه اجرای برنامه

 کار با threadها در لینوکس - قسمت دوم

در مقاله بعد به چگونگی همگام سازی نخ ها می پردازیم. ItPro باشید!


نویسنده : رامین غلامی تقی زاده

منبع : انجمن تخصصی فناوری اطلاعات ایران

هرگونه نشر و کپی برداری بدون ذکر منبع و نام نویسنده دارای اشکال اخلاقی می باشد

#قفل_های_mutex #مسائل_کلاسیک_همگام_سازی #سمافورها
عنوان
1 کار با threadها در لینوکس - قسمت اول رایگان
2 کار با threadها در لینوکس - قسمت دوم رایگان
3 کار با threadها در لینوکس - قسمت سوم رایگان
4 کار با threadها در لینوکس - قسمت چهارم رایگان
زمان و قیمت کل 0″ 0
0 نظر

هیچ نظری ارسال نشده است! اولین نظر برای این مطلب را شما ارسال کنید...

نظر شما
برای ارسال نظر باید وارد شوید.
از سرتاسر توسینسو
تنظیمات حریم خصوصی
تائید صرفنظر
×

تو می تونی بهترین نتیجه رو تضمینی با بهترین های ایران بدست بیاری ، پس مقایسه کن و بعد خرید کن : فقط توی جشنواره تابستانه می تونی امروز ارزونتر از فردا خرید کنی ....