PDA

عرض كامل الموضوع : البرمجة تحت نظام لنكس



Brave Heart
28-03-2004, 10:51 AM
[size=24:][b:][align=center:]بسم الله الرحمن الرحيم[/align:][/b:][/size:]



[b:]في هذا الدرس سنتطرق إلى العمليات و البرامج المنفذه في نظام تشغيل لنكس و سندرس عمل الدالة fork و عمل بعض الدوال

المستخدمه معها.



أولاً: من المعروف ان لكل عمليه task في نظام التشغيل لنكس رقم يعرف بالـ PID أي Process ID, و هذا الرقم لابد ان يكون موجباً

و إستخدام هذا الترقيم مهم جداً في تسهيل التعامل مع العمليات بدلاً من التعامل مع إسمها.

و من المعروف أيضاً في نظام تشغيل لنكس أن هناك العملية رقم 1 وهي عملية تتعلق ببدأ النظام init و هي العملية الأب لكل العمليات

أي أن كل العمليات هي مجرد أبناء للعمليه الأب init و من الممكن أن يكون للإبن أبن واحد أو أكثر.

و لكن يبقى السؤال وهو كيف نقوم بإنشاء عملية إبن من العملية الأب ؟

الإجابة هي بإستخدام الدالة fork و لكن كيف ؟ سنتطرق لها الآن.



الداله fork:

هذه الداله معرفة كالشكل التالي:[/b:]


[size=18:][b:][align=left:]#include "unistd.h"

#include "sys/types.h"

pid_t fork( void );[/align:][/b:][/size:]


[b:]طبعاً واضح مع تعريف الداله أنها لا تأخذ أي معاملات Parametar و لكنها تعيد متغير من نوع pid_t.

ما هو هذا النوع ؟

هذا هو متغير من نوع int إن صح القول مجازاً.



فهم طريقة عمل الدالة fork:

1. تستدعي العملية الأب ( برنامجنا الذي سنكتبه ) الدالة fork و تعيد لها رقم العملية الإبن الـ PID التابع للإبن.

2. يتولى نظام التشغيل لينكس مهمة عمل نسخة من البرنامج و محتويات الذاكره الخاصة بالعملية الأب إلى الجزء الخاص بالعملية الإبن

مما يعني أن العملية الإبن ستكون مماثله تماماً للعملية الأب.

3. الآن يصبح لدينا عمليتين هما العملية الأب و العملية الإبن يعملان في نفس الوقت.



و الدالة fork تعيد -1 عند حدوث خطأ معين و تعيد رقم الـ PID الخاص للإبن إلى الأب لكي يتحكم به و تعيد الرقم 0 (صفر) للعملية الإبن

للدلاله بأنها العملية الإبن.


قبل أن نأخذ مثال على الدالة fork لنأخذ الدالة getpid و هي تعيد متغير من نوع pid_t للعملية الحاليه.

فلو كتبنا هذا البرنامج:[/b:]


[size=18:][b:][align=left:]#include "stdio.h"

#include "sys/types.h"

#include "unistd.h"

int main()

{

pid_t pid;

pid = getpid();

printf("This process has the PID number: %d\n\n ", pid);

retutn 0;

}[/align:][/b:][/size:]


[b:]في هذا البرنامج سوف يطبع لنا رقم الـ PID للبرنامج الحالي.



الآن ننتقل إلى مثال الداله fork:[/b:]


[size=18:][b:][align=left:]#include "stdio.h"

#include "sys/types.h"

#include "unistd.h"

int main()

{

pid_t pid;

pid = fork();

if( pid == -1 ) // خطأ

{

printf("ERROR when forking\n\n");

exit(13);

}

else if( pid == 0 ) // في هذ الشرط ستعمل العمليه الإبن

{

printf("\nChild PID = %d\n", getpid());

}

else // هنا تنفذ العملية الأب

{

printf("\nParent PID = %d, Child PID = %d\n\n", getpid(), pid);

wait();

}

sleep(1);

return 0;

}[/align:][/b:][/size:]


[b:]في هذا البرنامج دللنا على كيفية إنشاء عمليه إبن من العملية الأب و لكن انا قلت انهما يعملان في نفس الوقت

و لنرى هذا الكود لكي ندلل على هذا الكلام.[/b:]

[size=18:][b:][align=left:]#include "stdio.h"

#include "sys/types.h"

#include "unistd.h"

int main()

{

pid_t pid;

int i;

pid = fork();

if( pid == -1 ) // خطأ

{

printf("ERROR when forking\n\n");

exit(13);

}

else if( pid == 0 ) // في هذ الشرط ستعمل العمليه الإبن

{

for( i = 0 ; i < 10 ; i++)

{

printf("Child, loop number %d\n", i);

sleep(1);

}

}

else // هنا تنفذ العملية الأب

{

for( i = 0 ; i < 20 ; i++)

{

printf("Parent, loop number %d\n", i);

sleep(2);

}

wait();

}

return 0;

}[/align:][/b:][/size:]


[b:]في هذا المثال لاحظ أن الـ Loop الخاصه في العملية الأب مقدارها 20 و الـ sleep مقداره 2 و الـ Loop الخاص في العملية الإبن مقداره 10

و الـ sleep مقداره واحد.

علماً أن الدالة sleep تنوم أو تُخمل البرنامج لعدد معين من الثواني بمقدار ما يعطى للداله.

الآن نفذ البرنامج وللاحظ النتائج سوف تبهرك كما أبهرتني أول مره.



و لكن الآن سوف تنتهي بطبيعة الحال العملية الإبن قبل العملية الأب, و لكن فرضاً في أني أريد أن أجعل الأب ينتظر العملية الإبن

ما هو الحل ؟!

الحل هو إستخدام الدالة wait المستخدمه اعلاه.



و هي لا تأخذ أو ترجع أي شيئ فيما عدا انها تنتظر العملية الإبن, لذلك العملية الأب حتى و إن إنتهت فهي تنتظر العملية الإبن حتى

تنتهي ثم يخرجان كلاهما.



الآن سنأخذ مثال عام على هذه المفاهيم و هو برنامج ضرب مصفوفات.

فكرته أن يقوم الإبن بضرب نصف المصفوفة فيما يقوم الأب بضرب نصفها ثم ينتظر العملية الإبن لينتهي و في هذه الاثناء تطبع العملية

الإبن نصف المصفوفة ثم تنتهي ثم بعد ذلك يقوم الأب بطباعة النصف الآخر ( أعرف أنكم ما فهمتو شي من هالكلام و لكن شوفو المثال )[/b:]


[size=18:][b:][align=left:]/*

This Programm is for multiply matrix.
It use some system calls such as fork.

It is powerfull for larg matrix multiplycations becose
it splet the matrix into two parts, a process multiplay
the first part and the other process multiply the
second part.
the child process multiply and prints its half then exit using exit function,
then the parent multiply and prints its half.

*/



#include

#define MAX_R 30 /* max row number */
#define MAX_C 30 /* max coloum number */

#define true 1
#define false 0


void read_matrix(int [][MAX_C], int, int);
void print_matrix(int [][MAX_C], int, int, int);
void multiply(int [][MAX_C], int [][MAX_C], int [][MAX_C],
int, int, int, int, int, int);

/* read rows & cols numbers and chick if number of coloums for the first matrix
is equal to number of rows for the second matrix */

int read_info(int *, int *, int *, int *);



int main()
{
int matrix1[MAX_R][MAX_C], matrix2[MAX_R][MAX_C];
int matrix_mul[MAX_R][MAX_C] = {0};
int row1, col1, row2, col2;


system("clear");

if(read_info(&row1, &col1, &row2, &col2)) /* chick if col1 = row2 */
{
printf("\n\n");

read_matrix(matrix1, row1, col1); /* read matrix 1 */
printf("\n\n");

read_matrix(matrix2, row2, col2); /* read matrix 1 */
printf("\n\n");

if(fork() == 0) /* child process do half multiply */
{
multiply(matrix1, matrix2, matrix_mul, row1, col1, row2, col2, 0, (row1/2));
print_matrix(matrix_mul,col2, 0, row1/2);
exit(0);
}
else /* parent process do the outher half */
{
multiply(matrix1, matrix2, matrix_mul, row1, col1, row2, col2, (row1/2), row1);
wait();
print_matrix(matrix_mul,col2, row1/2, row1);
}

printf("\n\n\n");
}
else /* can't multiply */
{
printf("\n\nERROR: Iligil coloum OR row size\n\n");
}

return 0;
}


/*---------------------------------------*/
void read_matrix(int matrix[][MAX_C], int row, int col)
{
int i, j;

for( i = 0 ; i < row ; i++ )
{
for( j = 0 ; j < col ; j++ )
{
printf("Enter element [%d][%d]: ", i+1, j+1);
scanf("%d", &matrix[i][j]);
}
printf("\n\n");
}
}
/*---------------------------------------*/
void print_matrix(int matrix[][MAX_C], int col, int begin, int end)
{
int i, j;

for( i = begin ; i < end ; i++ )
{
for( j = 0 ; j < col ; j++ )
{
printf(" %d\t", matrix[i][j]);
}
printf("\n");
}

}
/*---------------------------------------*/
void multiply(int matrix1[][MAX_C], int matrix2[][MAX_C], int multiply[][MAX_C],
int row1, int col1, int row2, int col2, int begin, int end)
{
int i, j, k;


for( k = 0 ; k < col1 ; k++ )
{
for( i = begin ; i < end ; i++ )
{
for( j = 0 ; j < col2 ; j++ )
multiply[i][j] = matrix1[i][k] * matrix2[k][j] + multiply[i][j];
}
}
}
/*---------------------------------------*/
int read_info(int *row1, int *col1, int *row2, int *col2)
{
printf("Enter number of rows for the first matrix: ");
scanf("%d", row1);

printf("Enter number of coloums for the first matrix: ");
scanf("%d", col1);

printf("Enter number of rows for the second matrix: ");
scanf("%d", row2);

printf("Enter number of coloums for the second matrix: ");
scanf("%d", col2);

if( *col1 != *row2)
return false;

return true;
}[/align:][/b:][/size:]


[b:]لاحظ مكان وجود الدالة wait !!

نعرف الآن أن العمليتين يعملان بالتناوب كما في المثال قبل السابق فلو لم نكتب الدالة wait لكان من الممكن أن يطبع

جزء من المصفوفة الأولى ثم في أثنائها ينتقل للعملية الثانيه و يطبع جزء من جزءها الآخر و هذا سيظهر نتائج خطأ, فنحن

قسمنا العمل على الجزء الأكثر إستهلاك لموارد المعالج CPU وهو ضرب المصفوفة.





أمثله على إستخدامات الدالة fork:

مثلاً لو كنت تعمل برنامج يدخل مجموعة من الارقام في ملف بحيث لابد من ترتيب المجموعة في النهاية فلو جعلنا المستخدم

يكتب الرقم الأول ثم نعمل fork لترتيب العناصر ثم في نفس الوقت يدخل الرقم الثاني ثم نعمل fork يرتب الاعداد ثم في نفس

الوقت يدخل الرقم الثالث و هكذا ...[/b:]



[size=24:][b:][align=center:]________________________________[/align:][/b:][/size:]


[size=18:][u:][b:]منقوول[/b:][/u:][/size:]

فرات
28-03-2004, 11:21 AM
صديقي فادي

اشكرك جزيل الشكر على المعلومات هاي
لكن صراحة وما بعد الصراحة
والله ما فهمت اشي حاولت اني افهم بس صعب كتير

والمشكلة الانجليزي
أخ ياصديقي الانجليزي

الجروووح
28-03-2004, 11:52 AM
اهلا بريف هارت .


والله جهود تشكر عليها من جد والله .


الله يساعدك ويعينك لكي ترتقي بهذا القسم الرائع والمهم .....

Brave Heart
28-03-2004, 12:22 PM
شكرا aboshtia و شكرا الجروووح لتاصلكم و تفاعلكم مع هذا القسم.

أرد على aboshtia فأقول, هذا نظام تشغيل يسمى لينكس. و هو نظام تستعمله شركات التزويد بالإنترنت خاصة و التي يسموها ISP و تعني Internet Service Provider أي مزد خدمة الإنترنت ولا تستطيع أي شركة تزويد العمل بدونه, لأنه هو أساس الإنترنت, و هو المزد الرئيسي, و يستخدم أيضاً في نظم الشبكات لأنه يخلوا من العثرات و النواقص و الثغرات فإمكانية إختراقه تساوي 0% و هذا ما يجعله النظام الأول في مستوى الحماية و الدعم.

و سبب عدم إستخدامه من العامة لأنه نظام صعب و للعمل عليه يجب ان تكتب Code خاص لعملية معينة ليس مثل الويندز Desktop يعني أي شيء تريده تستطيع فعله بالفور, بإستخدام الفأرة و هذا ما يجعل الإخصائيين على هذا النظام قلة و مميزين في عالم الإنترنت.

و لمعلومات أكثر حول هذا النظام فقد تم الشرح عنه في منتدى الحاسب الآلي و ها هو الرابط:
http://www.yabdoo.com/board/showthread.php?t=4959

أرجو الإستفادة منه.

و شكرا مرة أخرى لتفاعلكم.