ConstantinosNos Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Είμαι καινούριος εδώ και γράφω αυτό το ποστ με σκοπό τη βοήθειά σας σε μια εργασία μου,η οποία έχει ως εξής: Στην εργασία αυτή θα προσομοιώσετε τη λειτουργία καταγραφής, ενημέρωσης και έκδοσης λογαριασμών μιας εταιρίας κινητής τηλεφωνίας. Πιο συγκεκριμένα να υλοποπιήσετε 3 αρχεία πηγαίου κώδικα (.c) και αντίστοιχα εκτελέσιμα. symvolaio.c kartokiniti.c manager.c ( λειτουργεί ως διεπαφή μεταξύ των αρχείων δεδομένων και των δύο προηγούμενων αρχείων κώδικα, καθώς και τα τα ενεργοποιεί στην αρχή μέσω της fork-exec) Αρχεία εισόδου: programmata.txt Έχει μορφή (και έχει μόνο 2 γραμμές): V120 s 20 120 120 0.04 0.05 CU k 0.08 0.09 που μεταφράζεται ως εξής: Το V120 είναι πρόγραμμα συμβολαίου (s) με πάγιο 20 ευρώ το μήνα, με 120 δωρεάν λεπτά και 120 sms, και τα επιπλέον χρεώνονται με 0.04 ευρώ το κάθε λεπτό ομιλίας και 0.05 ευρώ το κάθε sms. Το CU είναι καρτοκινητό (k) και η χρέωσηζ θα είναι 0.08 ευρώ το κάθε λεπτό ομιλίας και 0.09 ευρώ το κάθε sms. pelates.txt Έχει μορφή : 6911111111 V120 6922222222 CU . . . που μεταφράζεται ως εξής: Το 6911111111 είναι κινητό του προγράμματος συμβολαίου V120 (περιγράφεται παραπάνω). Το 6922222222 είναι καρτοκινητό CU. kiniseis.txt Έχει μορφή : 6911111111 esteile sms 6911111111 milise 15 lepta 6922222222 esteile sms 6922222222 milise 7 lepta 6922222222 ananeosi 10 euro pliromes posa.txt 6922222222 ypoloipo ekkatharisi apodesmeusi . . . Tο πρόγραμμά σας θα πρέπει να υποστηρίζει τη σωστή ενημέρωση των λογαριασμών που αντιστοιχεί στις 9 λειτουργίες που φαίνονται στο ανωτέρω αρχείο: 1. αποστολή sms από χρήστη συμβολαίου 2. ομιλία χρήστη συμβολαίου 3. αποστολή sms από χρήστη καρτοκινητού (θα ενημερώνει αν εστάλει ή όχι, λόγω χαμηλού υπολοίπου) 4. ομιλία χρήστη καρτοκινητού (θα ενημερώνει αν μετά το τέλος της κλήσης το υπόλοιπο έγινε αρνητικό, οπότε και δε θα επιτρέπονται άλλες κλήσεις ή μηνύματα, μέχρι να γίνει ανέωση χρόνου και το υπόλοιπο γίνει θετικό) 5. ανανέωση χρόνου για καρτοκινητά 6. εκτύπωση ποσών πληρωμής για όλους τους χρήστες συμβολαίου (στο τέλος του μήνα) 7. επιστροφή υπολοίπου για χρήστες καρτοκινητού 8. μηδενισμός μετρητών (εκκαθάριση) χρηστών συμβολαίου (στην αρχή του μήνα) 9. αποδέσμευση όλων των δομών 10. γενίκευση προγράμματος για πολλά προγράμματα καρτοκινητής και πολλά προγράμματα συμβολαίου (αρχείο programmata.txt, με πάνω από δύο γραμμές) so far,αυτός είναι ο κώδικάς μου : #include<stdio.h> #include<conio.h> #include<ctype.h> #include<windows.h> #include<stdlib.h> struct subscriber { char phonenumber[9]; float amount; }s; void addrecords(); void listrecords(); void modifyrecords(); void payment(); char get; int main() { int password; int phonenumber; char choice; system("cls"); printf("\n\n\n\n\n\n\n\n\n**********************************************************************"); printf("\n\t\t---TELECOMMUNICATION COMPANY SYSTEM---"); printf("\n\t\t****************************************************************"); Sleep(2000); getch(); system("cls"); while (1) { system("cls"); printf("\n enter\n A : Prosthese neo arithmo.\n L : Katagrafh arithmwn"); printf("\n M : Tropopoihse arithmwn.\n P : Plhrwmh"); choice=getche(); choice=toupper(choice); switch(choice) { case 'P': payment();break; case 'A': addrecords();break; case 'L': listrecords();break; case 'M': modifyrecords();break; case 'E': system("cls"); printf("\n\n\t\t\t\tEUXARISTOUME"); Sleep(2000); exit(0); break; default: system("cls"); printf("Lathos eisodos"); printf("\nPathste opoiodhpote koumpi gia na sunexisete"); getch(); } } } void addrecords() { FILE *f; char test; f=fopen("c:/pelates_10.txt","ab+"); if(f==0) { f=fopen("c:/pelates_10.txt","wb+"); system("cls"); printf("Parakalw perimenete"); printf("/nPathste opoiodhpote koumpi gia na sunexisete"); getch(); } while(1) { system("cls"); printf("\n Plhktrologiste ton arithmo:"); scanf("%s",&s.phonenumber); fflush(stdin); printf("\n Plhktrologiste to poso:"); scanf("%f",&s.amount); fwrite(&s,sizeof(s),1,f); fflush(stdin); system("cls"); printf("1 To arxeio prostethike me epituxia"); printf("\n Press esc key to exit, any other key to add other record:"); test=getche(); if(test==27) break; } fclose(f); } void listrecords() { FILE *f; int i; if((f=fopen("c:/pelates_10.txt","rb"))==NULL) exit(0); system("cls"); printf("Phone Number\tAmount\n"); for(i=0;i<79;i++) printf("-"); while(fread(&s,sizeof(s),1,f)==1) { printf("\n%-10s\t\t%-20s\t\tRs. %.2f /-",s.phonenumber,s.amount); } printf("\n"); for(i=0;i<79;i++) printf("-"); fclose(f); getch(); } void searchrecords() { FILE *f; char phonenumber[20]; int flag=1; f=fopen("c:/pelates_10.txt","rb+"); if(f==0) exit(0); fflush(stdin); system("cls"); printf("Enter Phone Number to search in our database"); scanf("%s", phonenumber); while(fread(&s,sizeof(s),1,f)==1) { if(strcmp(s.phonenumber,phonenumber)==0) { system("cls"); printf(" Record Found "); printf("\n\nPhonenumber: %s\nName: %s\nAmount: Rs.%0.2f\n",s.phonenumber,s.amount); flag=0; break; } else if(flag==1) { system("cls"); printf("Requested Phone Number Not found in our database"); } } getch(); fclose(f); } void modifyrecords() { FILE *f; char phonenumber[20]; long int size=sizeof(s); if((f=fopen("c:/pelates_10.txt","rb+"))==NULL) exit(0); system("cls"); printf("Enter phone number of the subscriber to modify:"); scanf("%[^\n]",phonenumber); fflush(stdin); while(fread(&s,sizeof(s),1,f)==1) { if(strcmp(s.phonenumber,phonenumber)==0) { system("cls"); printf("\n Eisagete arithmo tilefwnou:"); scanf("%s",&s.phonenumber); printf("\n Eisagete poso: "); scanf("%f",&s.amount); fseek(f,-size,SEEK_CUR); fwrite(&s,sizeof(s),1,f); break; } } fclose(f); } void payment() { FILE *f; char phonenumber[20]; long int size=sizeof(s); float amt; int i; if((f=fopen("c:/pelates_10.txt","rb+"))==NULL) exit(0); system("cls"); printf("Enter phone number of the subscriber for payment"); scanf("%[^\n]",phonenumber); fflush(stdin); while(fread(&s,sizeof(s),1,f)==1) { if(strcmp(s.phonenumber,phonenumber)==0) { system("cls"); printf("\n Phone No.: %s",s.phonenumber); printf("\n Trexon poso: %f",s.amount); printf("\n"); for(i=0;i<79;i++) printf("-"); printf("\n\nEissagete to poso plirwmis :"); fflush(stdin); scanf(" %f",&amt); s.amount=s.amount-amt; fseek(f,-size,SEEK_CUR); fwrite(&s,sizeof(s),1,f); break; } } system("cls"); printf("Euxaristoume %s "); getch(); fclose(f); } Πως μπορώ να το κάνω σε 3 αρχεία όπως ζητάει;Αny ideas?
lion2486 Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 οι αντηρήσεις μου πάνω στον κωδικά σου: - Γιατί έχεις βάλει το sleep? Νομίζω θα γίνει ενοχλητικό σε κάποια σημεία... - Γιατί επαναλαμβάνεις ίδια κομμάτια κώδικα; Μπορείς να κάνεις μια συνάρτηση που θα κάνει την αναζήτηση και θα επιστρέφει το struct. Όσον αφορά τώρα τα 3 αρχεία, θες 3 αρχεία ή 3 εκτελέσιμα προγράμματα; Αν θες απλά 3 αρχεία μετακινείς το implementation των συναρτήσεων στο αρχείο με τον πιο συσχετιζόμενο τίτλο. Υ.Γ.: Καλως όρισες στην παρέα μας!
kaliakman Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Μπορείς να κάνεις κάτι που μας είχανε πει στην δική μου σχολή αν θες 3 αρχεία. 1 αρχείο Implementation που γράφεις μέσα όλες τις συναρτήσεις που υλοποιείς 1 αρχείο επικεφαλίδας που έχει τα πρότυπα των συναρτήσεων 1 αρχείο επικεφαλίδας που έχει ότι types έχεις χρησιμοποιήσει πχ typedefs,defines. Το αποτέλεσμα είναι και καλά να φτιάξεις κάτι σαν βιβλιοθήκη ώστε να πρέπει να δείς μόνο το δεύτερο αρχείο για να δεις τις λειτουργίες του προγράμματος χωρίς να σε απασχολεί η υλοποιήση.
παπι Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Άλλο ένα μπουμπούκι καθηγητής. Ανάθεμα αν ξέρει και ο ίδιος το τι ζητάει. Σίγουρα θέλει 3 προγράμματα/εκτελέσιμα και... αυτά, τα άλλα δεν βγάζουν νόημα. Καλό θα ήταν να πάρεις κάνα βιβλίο για c και να αφιερώσεις σε αυτό τον χρόνο σου, παρά σε αυτά που σε διδάσκει ο καθηγητής. 3
nrkmaiden Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Τη μονή παρατήρηση που έχω να κάνω για τώρα εινα ότι δε χρησιμοποιεις αυτά που σ λέει η εκφώνηση (fork / exec), άρα αν και σωστό αποτέλεσμα μπορεί να στην πιάσει λάθος ανάλογα με το τι έκανε στο μάθημα.
M2000 Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Δεν μπορώ να καταλάβω τι θέλει να πετύχει ο καθηγητής με το fork. Έχει κ νέες καμία ιδέα;
lion2486 Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Δεν μπορώ να καταλάβω τι θέλει να πετύχει ο καθηγητής με το fork. Έχει κ νέες καμία ιδέα; Θέλει να πετύχει να έχει ανεξάρτητες διεργασίες στο σύστημα για την κάθε λειτουργία του. 1
M2000 Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Και πάλι αυτό δεν λέει τίποτα. Γιατί θέλει ανεξάρτητες διεργασίες; Ένα αρχείο παίρνει και βγάζει ένα αποτέλεσμα; Δεν έχουμε ασύγχρονες διεργασίες. (έτσι το κατάλαβα).
lion2486 Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Και πάλι αυτό δεν λέει τίποτα. Γιατί θέλει ανεξάρτητες διεργασίες; Ένα αρχείο παίρνει και βγάζει ένα αποτέλεσμα; Δεν έχουμε ασύγχρονες διεργασίες. (έτσι το κατάλαβα). Για να μάθουν να χρησιμοποιούν την fork...
ConstantinosNos Δημοσ. 7 Ιουνίου 2016 Μέλος Δημοσ. 7 Ιουνίου 2016 οι αντηρήσεις μου πάνω στον κωδικά σου: - Γιατί έχεις βάλει το sleep? Νομίζω θα γίνει ενοχλητικό σε κάποια σημεία... - Γιατί επαναλαμβάνεις ίδια κομμάτια κώδικα; Μπορείς να κάνεις μια συνάρτηση που θα κάνει την αναζήτηση και θα επιστρέφει το struct. Όσον αφορά τώρα τα 3 αρχεία, θες 3 αρχεία ή 3 εκτελέσιμα προγράμματα; Αν θες απλά 3 αρχεία μετακινείς το implementation των συναρτήσεων στο αρχείο με τον πιο συσχετιζόμενο τίτλο. Υ.Γ.: Καλως όρισες στην παρέα μας! Καλώς σας βρήκα!Ναι 3 εκτελέσιμα ζητάει Τη μονή παρατήρηση που έχω να κάνω για τώρα εινα ότι δε χρησιμοποιεις αυτά που σ λέει η εκφώνηση (fork / exec), άρα αν και σωστό αποτέλεσμα μπορεί να στην πιάσει λάθος ανάλογα με το τι έκανε στο μάθημα. fork δεν έχω ιδέα πως να κάνω γι αυτό και δε την έβαλα καθόλου
_Gikoskos_ Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Μου φαίνεται πως το νόημα της άσκησης ήταν να χρησιμοποιήσεις την fork, αν σας είπε να κάνετε 3 εκτελέσιμα. Όλη η άσκηση είναι πολύ παράξενη όμως, γιατί η fork() δημιουργεί καινούργια θυγατρική διεργασία που τρέχει παράλληλα με το κύριο πρόγραμμά σου, άλλα δεν είδα που μπορεί να χρησιμεύσει ο παραλληλισμός σε αυτήν την άσκηση όπως παρατήρησε ο Μ2000. Το παπί έχει δίκιο γιατί και το να διαχωρίσεις συναρτήσεις σε διαφορετικό εκτελέσιμο είναι πάλι πολύ παράξενο, δηλαδή δεν πρόκειται να το δεις πουθενά σαν τεχνική. Πέρα από κριτική στην άσκησης, θα σου πω τι σου ζητάει ο καθηγητής σου, αν κατάλαβα καλά. Σου ζητάει να μεταφέρεις όλες τις συναρτήσεις που εκτελούν ξεχωριστές λειτουργίες (δηλαδή τις λειτουργίες που ζητάς στην αρχική σου main από τον χρήστη) σε διαφορετικά αρχεία C και να τις μετονομάσεις σε main ώστε η κάθε μία να είναι ξεχωριστό πρόγραμμα. Από κει και πέρα, αντί να τρέχεις τις συναρτήσεις στο switch/case που έχεις στην main, όπως κάνεις τώρα, σου ζητάει να εκτελέσεις το αντίστοιχο πρόγραμμα. Δηλαδή κάνε αρχεία payment.c, addrecords.c και πάει λέγοντας, βάλε μέσα τις αντίστοιχες συναρτήσεις και όποιες άλλες βοηθητικές μεταβλητές ή συναρτήσεις χρησιμοποιούν, και μετονόμασέ τες σε int main(int argc, char *argv[]) για να μπορούν να γίνονται compile σε εκτελέσιμο. Τώρα η fork είναι μία συνάρτηση που δεν παίρνει παραμέτρους και κάθε φορά που την καλείς, δημιουργεί μία θυγατρική διεργασία που τρέχει παράλληλα με όλες τις υπόλοιπες διεργασίες. Είναι δηλαδή σαν να εκτελείς ένα δεύτερο πρόγραμμα μέσα απο το κυρίως πρόγραμμά σου. Φαντάσου το κάπως έτσι δηλαδή: _ θυγατρική_διεργασία κύρια_διεργασία.exe --------------- (κλήση της fork()) / \_ κύρια_διεργασία και επιστρέφει στην κύρια διεργασία μία μεταβλητή τύπου pid_t όπου είναι το αναγνωριστικό της θυγατρικής που μπορείς να το χρησιμοποιήσεις σε περεταίρω συναρτήσεις, και στην θυγατρική σου διεργασία το 0. Αν αποτύχει επιστρέφει -1 αλλά σπάνιο να αποτύχει. Παρεπιπτόντως η fork() είναι κλήση συστήματος Unix. Αν γράφετε κώδικα και κάνετε compile σε Windows, και ο καθηγητής σου σας είπε να χρησιμοποιήσετε την fork() κάτι δεν πάει καλά. To Windows έχει μία δικιά του κλήση συστήματος για διεργασίες, την CreateProcess που κάνει πάνω κάτω την ίδια δουλειά. Η ομάδα κλήσεων exec απλά εκτελούν το εκτελέσιμο .exe που τους δίνεις σαν παράμετρο. Επίσης με την exec μπορείς να περάσεις παραμέτρους στο πρόγραμμα που θα εκτελέσεις, τις οποίες τις διαβάζεις μεσω του argument vector (μεταβλητή *argv[] στις παραμέτρους της main). Λέω ομάδα κλήσεων, γιατί έχει διάφορες συναρτήσεις exec που κάνουν το ίδιο πράγμα (execlp, execvp, execv κτλ) με την διαφορά ότι περνάνε τις παραμέτρους στο καινούργιο πρόγραμμα με άλλο τρόπο. Μπορείς να φανταστείς ότι η exec είναι σαν την system που χρησιμοποιείς στον κώδικά σου. Η διαφορά είναι ότι η exec σταματάει την εκτέλεση του προγράμματός σου και τρέχει το καινούργιο πρόγραμμα, χωρίς να επιστρέψει, ενώ η system εκτελεί το πρόγραμμα που της έδωσες σαν παράμετρο και μετά επιστρέφει στο κυρίως πρόγραμμα που την κάλεσε. Η διαφορά της exec με την fork είναι πως, η fork δημιουργεί έναν κλώνο της διεργασίας που την κάλεσε, και συνεχίζει να τρέχει απο μόνη της παράλληλα με την διεργασία γονιό της. Όταν λέω κλώνο, εννοώ πως η fork αντιγράφει τα περισσότερα χαρακτηριστικά της διεργασίας που την κάλεσε, μέχρι το σημείο εκείνο, όπως μεταβλητές, file descriptors, locks κτλ. Για παράδειγμα int main(int argc, char *argv[]) { int i = 0, j = 1; pid_t new_process; if (!(new_process = fork())) { //εδώ μπαίνει ο κώδικας της νέας διεργασίας σου //οι μεταβλητές i, j, new_process υπάρχουν στην νέα διεργασία //η μεταβλητή z δεν αντιγράφεται, γιατί δημιουργείται μετά την κλήση της fork() //η new_process είναι 0 στην καινούργια διεργασία printf("%d\n", new_prcoess); //εκτυπώνει 0 } //από εδώ και κάτω συνεχίζει κανονικά το πρόγραμμα χωρίς να σταματήσει int z = 1545; //η new_process παίρνει το αναγνωριστικό της θυγατρικής διεργασίας που τρέχει πιο πάνω, δηλαδή είναι =/= του 0 printf("%d\n", new_prcoess); //εκτυπώνει 1293292 (τυχαίος αριθμός που ορίζεται ως το αναγνωριστικό της διεργασίας) return 0; } Αν τρέξεις fork() στο πρόγραμμά σου και ψάξεις το εκτελέσιμό σου μέσα στον Task Manager του λειτουργικού σου, θα παρατηρήσεις πως έχει δύο εκτελέσιμες διεργασίες με το ίδιο όνομα, αντί για μία. Η exec δεν εκτελείται παράλληλα με το πρόγραμμά σου, απλά σταματάει για να εκτελέσει το καινούργιο πρόγραμμα και δεν επιστρέφει ποτέ: int main(int argc, char *argv[]) { execl("AssassinsCreed2.exe", "AssassinsCreed2.exe", NULL); //ό,τι κώδικα και να βάλεις απο εδώ και κάτω δεν θα εκτελεστεί ποτέ //η exec αντικαθιστά την διεργασία που την κάλεσε, με //το AssassinsCreed2.exe χωρίς να επιστρέψει ποτέ (παρά μόνο αν υπάρχει σφάλμα, όπως αν δεν βρήκε το εκτελέσιμο που της έδωσες σαν παράμετρο) return 0; } Ο συνδυασμός fork/exec για να τρέχεις εκτελέσιμα παράλληλα με το πρόγραμμά σου, χωρίς να το αντικαθιστάς, είναι πολύ συνηθισμένη τεχνική και ονομάζεται spawn. Εσύ όταν κάνεις compile τα payment.c, addrecords.c κτλ σε payment.exe, addrecords.exe κτλ, θα βάλεις στην θέση των κλήσεων που κάνεις στην switch/case στην main σου, ένα συνδυασμό fork/exec της μορφής: if (!fork()) execl("payment.exe", "payment.exe", NULL); Edit: Αυτό παρ'ολ'αυτά δεν έχει κανένα νόημα σε προγραμματιστικό περιβάλλον windows εκτός και αν χρησιμοποιείς compiler που είναι port από compiler του Linux (βλέπε cygwin, mingw-w64 κτλ) και προσφέρει αυτές τις προαιρετικές λειτουργίες σαν wrapper πάνω απο την CreateProcess του WinAPI. 1
lion2486 Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Θα μπορούσε να εννοεί και ένα εκτελέσιμο που οι άλλες λειτουργίες εκτελούνται σε διαφορετικές διεργασίες (χωρίς exec δηλαδή..) Δεν είναι πολύ κατανοητό το ζητούμενο.
ConstantinosNos Δημοσ. 7 Ιουνίου 2016 Μέλος Δημοσ. 7 Ιουνίου 2016 Σε linux τη θέλει και μάλιστα μας έχει δώσει αυτά σαν οδηγό: Η εφαρμογή θα κληθεί με τον τρόπο: ./ergasia1 –pr programmata –pe pelates –k kiniseis όπου: ergasia1 είναι το εκτελέσιμο του προγράμματος programmata, pelates και kiniseis είναι τα 3 αρχεία εισόδου, που αναλύθηκαν στις προηγούμενες σελίδες της εργασίας Μου φαίνεται πως το νόημα της άσκησης ήταν να χρησιμοποιήσεις την fork, αν σας είπε να κάνετε 3 εκτελέσιμα. Όλη η άσκηση είναι πολύ παράξενη όμως, γιατί η fork() δημιουργεί καινούργια θυγατρική διεργασία που τρέχει παράλληλα με το κύριο πρόγραμμά σου, άλλα δεν είδα που μπορεί να χρησιμεύσει ο παραλληλισμός σε αυτήν την άσκηση όπως παρατήρησε ο Μ2000. Το παπί έχει δίκιο γιατί και το να διαχωρίσεις συναρτήσεις σε διαφορετικό εκτελέσιμο είναι πάλι πολύ παράξενο, δηλαδή δεν πρόκειται να το δεις πουθενά σαν τεχνική. Πέρα από κριτική στην άσκησης, θα σου πω τι σου ζητάει ο καθηγητής σου, αν κατάλαβα καλά. Σου ζητάει να μεταφέρεις όλες τις συναρτήσεις που εκτελούν ξεχωριστές λειτουργίες (δηλαδή τις λειτουργίες που ζητάς στην αρχική σου main από τον χρήστη) σε διαφορετικά αρχεία C και να τις μετονομάσεις σε main ώστε η κάθε μία να είναι ξεχωριστό πρόγραμμα. Από κει και πέρα, αντί να τρέχεις τις συναρτήσεις στο switch/case που έχεις στην main, όπως κάνεις τώρα, σου ζητάει να εκτελέσεις το αντίστοιχο πρόγραμμα. Δηλαδή κάνε αρχεία payment.c, addrecords.c και πάει λέγοντας, βάλε μέσα τις αντίστοιχες συναρτήσεις και όποιες άλλες βοηθητικές μεταβλητές ή συναρτήσεις χρησιμοποιούν, και μετονόμασέ τες σε int main(int argc, char *argv[]) για να μπορούν να γίνονται compile σε εκτελέσιμο. Τώρα η fork είναι μία συνάρτηση που δεν παίρνει παραμέτρους και κάθε φορά που την καλείς, δημιουργεί μία θυγατρική διεργασία που τρέχει παράλληλα με όλες τις υπόλοιπες διεργασίες. Είναι δηλαδή σαν να εκτελείς ένα δεύτερο πρόγραμμα μέσα απο το κυρίως πρόγραμμά σου. Φαντάσου το κάπως έτσι δηλαδή: _ θυγατρική_διεργασία κύρια_διεργασία.exe --------------- (κλήση της fork()) / \_ κύρια_διεργασία και επιστρέφει στην κύρια διεργασία μία μεταβλητή τύπου pid_t όπου είναι το αναγνωριστικό της θυγατρικής που μπορείς να το χρησιμοποιήσεις σε περεταίρω συναρτήσεις, και στην θυγατρική σου διεργασία το 0. Αν αποτύχει επιστρέφει -1 αλλά σπάνιο να αποτύχει. Παρεπιπτόντως η fork() είναι κλήση συστήματος Unix. Αν γράφετε κώδικα και κάνετε compile σε Windows, και ο καθηγητής σου σας είπε να χρησιμοποιήσετε την fork() κάτι δεν πάει καλά. To Windows έχει μία δικιά του κλήση συστήματος για διεργασίες, την CreateProcess που κάνει πάνω κάτω την ίδια δουλειά. Η ομάδα κλήσεων exec απλά εκτελούν το εκτελέσιμο .exe που τους δίνεις σαν παράμετρο. Επίσης με την exec μπορείς να περάσεις παραμέτρους στο πρόγραμμα που θα εκτελέσεις, τις οποίες τις διαβάζεις μεσω του argument vector (μεταβλητή *argv[] στις παραμέτρους της main). Λέω ομάδα κλήσεων, γιατί έχει διάφορες συναρτήσεις exec που κάνουν το ίδιο πράγμα (execlp, execvp, execv κτλ) με την διαφορά ότι περνάνε τις παραμέτρους στο καινούργιο πρόγραμμα με άλλο τρόπο. Μπορείς να φανταστείς ότι η exec είναι σαν την system που χρησιμοποιείς στον κώδικά σου. Η διαφορά είναι ότι η exec σταματάει την εκτέλεση του προγράμματός σου και τρέχει το καινούργιο πρόγραμμα, χωρίς να επιστρέψει, ενώ η system εκτελεί το πρόγραμμα που της έδωσες σαν παράμετρο και μετά επιστρέφει στο κυρίως πρόγραμμα που την κάλεσε. Η διαφορά της exec με την fork είναι πως, η fork δημιουργεί έναν κλώνο της διεργασίας που την κάλεσε, και συνεχίζει να τρέχει απο μόνη της παράλληλα με την διεργασία γονιό της. Όταν λέω κλώνο, εννοώ πως η fork αντιγράφει τα περισσότερα χαρακτηριστικά της διεργασίας που την κάλεσε, μέχρι το σημείο εκείνο, όπως μεταβλητές, file descriptors, locks κτλ. Για παράδειγμα int main(int argc, char *argv[]) { int i = 0, j = 1; pid_t new_process; if (!(new_process = fork())) { //εδώ μπαίνει ο κώδικας της νέας διεργασίας σου //οι μεταβλητές i, j, new_process υπάρχουν στην νέα διεργασία //η μεταβλητή z δεν αντιγράφεται, γιατί δημιουργείται μετά την κλήση της fork() //η new_process είναι 0 στην καινούργια διεργασία printf("%d\n", new_prcoess); //εκτυπώνει 0 } //από εδώ και κάτω συνεχίζει κανονικά το πρόγραμμα χωρίς να σταματήσει int z = 1545; //η new_process παίρνει το αναγνωριστικό της θυγατρικής διεργασίας που τρέχει πιο πάνω, δηλαδή είναι =/= του 0 printf("%d\n", new_prcoess); //εκτυπώνει 1293292 (τυχαίος αριθμός που ορίζεται ως το αναγνωριστικό της διεργασίας) return 0; } Αν τρέξεις fork() στο πρόγραμμά σου και ψάξεις το εκτελέσιμό σου μέσα στον Task Manager του λειτουργικού σου, θα παρατηρήσεις πως έχει δύο εκτελέσιμες διεργασίες με το ίδιο όνομα, αντί για μία. Η exec δεν εκτελείται παράλληλα με το πρόγραμμά σου, απλά σταματάει για να εκτελέσει το καινούργιο πρόγραμμα και δεν επιστρέφει ποτέ: int main(int argc, char *argv[]) { execl("AssassinsCreed2.exe", "AssassinsCreed2.exe", NULL); //ό,τι κώδικα και να βάλεις απο εδώ και κάτω δεν θα εκτελεστεί ποτέ //η exec αντικαθιστά την διεργασία που την κάλεσε, με //το AssassinsCreed2.exe χωρίς να επιστρέψει ποτέ (παρά μόνο αν υπάρχει σφάλμα, όπως αν δεν βρήκε το εκτελέσιμο που της έδωσες σαν παράμετρο) return 0; } Ο συνδυασμός fork/exec για να τρέχεις εκτελέσιμα παράλληλα με το πρόγραμμά σου, χωρίς να το αντικαθιστάς, είναι πολύ συνηθισμένη τεχνική και ονομάζεται spawn. Εσύ όταν κάνεις compile τα payment.c, addrecords.c κτλ σε payment.exe, addrecords.exe κτλ, θα βάλεις στην θέση των κλήσεων που κάνεις στην switch/case στην main σου, ένα συνδυασμό fork/exec της μορφής: if (!fork()) execl("payment.exe", "payment.exe", NULL); Edit: Αυτό παρ'ολ'αυτά δεν έχει κανένα νόημα σε προγραμματιστικό περιβάλλον windows εκτός και αν χρησιμοποιείς compiler που είναι port από compiler του Linux (βλέπε cygwin, mingw-w64 κτλ) και προσφέρει αυτές τις προαιρετικές λειτουργίες σαν wrapper πάνω απο την CreateProcess του WinAPI. εκεί που αναφέρεις payment.c, addrecords.c θα μπορούσα να βάλω τα 3 αρχεία που ζητάει δλδ programmata,pelates,kiniseis έτσι; Επίσης έχω ακόμα ένα θέμα...Πως θα ανοίξω την εργασία από τα linux; Mέσω terminal;
SIMkartaUK Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 (επεξεργασμένο) εγώ παντως θα χρησιμοποιούσα περισσότερο pointers και pass by reference για να μην πιάνει πολύ μνήμη.. example: http://c.learncodethehardway.org/book/ex16.html προσωπικά μου αρέσει πολύ ο αντικειμενοστραφής προγραμματισμός με C άν και έχει περισσότερη δουλιτσα https://www.cs.rit.edu/~ats/books/ooc.pdf Επεξ/σία 7 Ιουνίου 2016 από SIMkartaUK
anon667 Δημοσ. 7 Ιουνίου 2016 Δημοσ. 7 Ιουνίου 2016 Off-topic Χρειαζόμαστε wtf counter που θα αυξάνει με αυτά που γράφονται από διάφορα μέλη του φόρουμ. Όταν θα φτάνει σε critical point θα ενεργοποιείται αυτόματο report σε moderator. /Off-topic 1
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα