Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 29 mar 2024, o 11:09


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 16 ] 
Autor Wiadomość
PostNapisane: 18 sie 2014, o 08:21 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

Programowania w C na dobrą sprawę uczyłem się na mikrokontrolerach. Dopiero jakiś czas temu postanowiłem wykorzystać posiadane Raspberry Pi do czegoś więcej, niż tylko odpalanie cudzych aplikacji. Napisałem obecnie kilka niewielkich programików. Podczas ich tworzenia posługiwałem się wiedzą i przyzwyczajeniami wyniesionymi z MCU. I tak na przykład chcąc wykonywać jakieś zadanie cyklicznie w pętli głównej stosuję licznik programowy. Jeśli w programie stosuję bibliotekę wiringPi (dostęp do GPIO na zasadach podobnych do Arduino), korzystam z zawartej w niej instrukcji milis().

Tak się jednak zastanawiam.... Może pod Linuksem istnieje jakaś prostsza/lepsza metoda? Może da się po prostu zarejestrować wskaźnik do jakiejś funkcji tak, żeby program automatycznie wywoływał ją w określonych przedziałach czasu? Chodzi mi tutaj m.in. o obsługę serwera. Mog to zrobić w bardziej elegancki sposób, czy pozostają mi liczniki, dokładnie tak jak na AVR-ach?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 08:54 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 12 maja 2013
Posty: 568
Zbananowany użytkownik

Pomógł: 31

W Linuxie możesz wstrzymywać pracę programu na określony czas, funkcja: sleep() i nanosleep(), nanosleep wymaga struktury timespec.
Jak chcesz programować w Linuxie to proponuję C++.

_________________
Und schreien

Spring
Erlöse mich
Spring
...



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 09:09 
Offline
Użytkownik

Dołączył(a): 05 lut 2013
Posty: 302
Pomógł: 19

Programujac na uC nie masz systemu, tutaj masz system i wiele rzeczy robi za Ciebie.
Pamietaj tez ze AVR jest systemem czasu rzeczywistego, tzn mozesz przewidziec ile czasu co zajmie, a linux juz nie.
Tutaj musisz radzic sobie innymi metodami, forkowanie, oczekiwania na procesy podrzedne.
Np serwery TCP/UDP pisze sie tak, ze glowny proces nasluchuje czy jest nowe polaczenie, a jak cos sie znajdzie to tworzy swoja kopie (fork) ktora zajmuje sie tylko i wylacznie obsluga tego polaczenia, tak aby zwis transmisji nie zablokowal mozliwosci przyjecia kolejnego polaczenia.
No ale jesli mimo wszystko bedziesz potrzebowal timerow to w linuxie odpowiednikiem przerwan z licznikow beda sygnaly (signal()) oraz interesowac bedzie cie ich ustawianie (setitimer());



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 10:50 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

PROTON napisał(a):
W Linuxie możesz wstrzymywać pracę programu na określony czas, funkcja: sleep() i nanosleep(), nanosleep wymaga struktury timespec.


To wiem, zwykle wykorzystuję usleep().


Cytuj:
Jak chcesz programować w Linuxie to proponuję C++.


Na razie nie czuję takiej potrzeby, żeby uczyć się kolejnego języka. Moim głównym zainteresowaniem jest elektronika, a w związku z tym potrzebuję C do programowania MCU. Linux jest niejako "na boku", gdy chcę dodać do moich projektów jakiś "wyższy poziom' - np. interfejs deamon czytający informacje z czujników i przekazujący je do skryptu PHP udostępnionego na serwerze WWW.

charsz napisał(a):
Pamietaj tez ze AVR jest systemem czasu rzeczywistego, tzn mozesz przewidziec ile czasu co zajmie, a linux juz nie.


Zdaję sobie z tego sprawę, ale szczególnie mi to nie przeszkadza. AVR-y i Linuksa wykorzystują po prostu do innych celów.

Cytuj:
Tutaj musisz radzic sobie innymi metodami, forkowanie, oczekiwania na procesy podrzedne.
Np serwery TCP/UDP pisze sie tak, ze glowny proces nasluchuje czy jest nowe polaczenie, a jak cos sie znajdzie to tworzy swoja kopie (fork) ktora zajmuje sie tylko i wylacznie obsluga tego polaczenia, tak aby zwis transmisji nie zablokowal mozliwosci przyjecia kolejnego polaczenia.


Hmm... Czy opanowanie takiej metody pisania programów jest czymś szczególnie trudnym w porównaniu z obsługą wielu zadań za pomocą timerów na uC? Od czego powinienem zacząć? Z jakimi zagadnieniami się zapoznać?

------------------------ [ Dodano po: 18 minutach ]

mokrowski napisał(a):
Napisz najdokładniej co chcesz zrobić. Możliwości w GNU/Linux jest takie zatrzęsienie że nie wiadomo co proponować.
Chodzi Ci o serwer sieciowy czy komunikację wewnętrzną czy ew. wykonywanie periodyczne działania w aplikacji czy reakcję na zdarzenie...


Hmm... Właściwie wszystko (a właściwie większość z powyższych po trochu). W tej chwili próbuję napisać program (deamona), który będzie pracował w tle, regularnie odczytując status paru urządzeń na MCU. Napisałem już funkcje odpowiedzialne za komunikację z tymi urządzeniami. Wykorzystuję do tego celu pakiety UDP, a odczytywane informacje są przechowywane w strukturze. Ta sama struktura trzyma "namiary" na urządzenie. W ten sposób struktura tworzy rodzaj wirtualnej reprezentacji urządzenia:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Dzięki zastosowaniu takiego podejścia mogę utworzyć całą tablicę "urządzeń" i odświeżać ich dane jedno po drugim.

W tym wypadku chodzi więc tylko o to, żeby w regularnych odstępach czasu wykonywać operację odświeżania danych zawartych w strukturach (funkcja read_device(&device)). Oczywiście funkcja nie tylko odczytuje te dane, ale także zajmuje się ich wstępną obróbką, np. przetwarza int na float.


Teraz jednak idziemy dalej. Program musi też działać jako serwer, udostępniający te dane użytkownikowi i/lub innym programom (np. skryptowi PHP) w postaci "raportów". Innymi słowy zestawiamy z serwerem połączenie TCP, wysyłamy komendę, a on odsyła odpowiedni raport o bieżących wynikach pomiarów.

To najważniejsze funkcje, ale nie jedyne. Program powinien też cyklicznie sprawdzać jedną z kluczowych wartości i w przypadku wykrycia przekroczenia ustalonego limitu wysyłać wiadomość e-mail do użytkownika. Co jakiś czas "raport" powinien też trafiać do pliku. Tym jednak zajmę się później. W planach "na kiedyś" jest też ładowanie wyników pomiarów do jakiejś bazy danych.

Generalnie program staram się napisać tak, żeby w przyszłości można było za jego pomocą odczytywać i kontrolować także inne zbudowane przeze mnie urządzenia na uC, pracujące w sieci - kwestia dodania kolejnej struktury odpowiadającej ich charakterystyce i zarejestrowania kolejnej funkcji cyklicznie czytającej dane.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 12:08 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

mokrowski napisał(a):
Tu zaproponuję najprostsze ze znanych mi podejść (KISS :-) ...
Jeśli chcesz odpytywać urządzenia z granulacją sekund, zastosuj wywołanie (tu będę podawał manuale): man 2 alarm, które pozwoli Ci ustalić interwał w sekundach na odpytanie oraz: man 2 signal, które pozwoli Ci zarejestrować funkcję obsługi tegoż sygnału. Nawet ostatnio podawałem przykład signal w innym wątku... topic8102.html. W tamtym wątku było to dla innych sygnałów ale zasada ta sama.

Jeśli chcesz odpytywać urządzenia z granulacją mniejszą niż sekundy, użyj: man 2 setitimer oraz signal do rejestracji obsługi sygnału alarm.


Hmm... A można w ten sposób ustawić kilka alarmów, przypisanych do różnych funkcji, które będą wywoływane z różną częstotliwością, niezależnie od siebie? W końcu tak właśnie działają liczniki w AVR-ach...
Można przypisać kilka funkcji do jednego alarmu?


mokrowski napisał(a):
Wystarczy że program udostępni plik w którym zapisze dane z czujników w formacie łatwym do sparsowania od strony PHP lub innych technologii. Pamiętaj jednak o założeniu blokady na plik poprzez: man 2 flock (zerknij na flagi, pewnie będzie najlepsza LOCK_SH) w trakcie pisania do niego i sprawdzaniu blokady ze strony PHP przed odczytem.


To najprostsze rozwiązanie - myślałem o nim początkowo, ale teraz skłaniam się raczej ku rozwiązaniu z serwerem. Powód jest prosty - do pliku dostanę się tylko z tej samej maszyny. Mając serwer mogę w przyszłości pomyśleć np. o dopisaniu jakiejś aplikacji na androida, która posłuży do zdalnej obsługi zbudowanych urządzeń. Poza tym plik w wygodny sposób pozwoli mi tylko wyciągać dane z czujników. Dzięki serwerowi będę mógł też przesyłać jakieś polecenia do wykonania sterownikom (np. załączanie światła).



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 12:49 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

mokrowski napisał(a):
Tu jednak zastanów się czy nie warto na maszynie z procesem zbierającym dane który to wystawi je w pamięci współdzielonej/gnieździe lokalnym, uruchomić PHP które szybciej i łatwiej obsłuży protokoły HTML/JSON/XML i inne ,,grube". To pozwoli szybko zbudować aplikację bez ładowania się w budowanie serwera HTTP w języku C :-) A PHP czy inna technologia webowa, obsłuży Ci i wysyłanie danych do czujników i zbieranie z nich... Osobiście PHP nie stosuję i wolę Python'a i Django :-)


Nie mam zamiaru budować serwera HTTP, bo ten już mam (lighttpd) na tym samym urządzeniu i to właśnie on wykonuje skrypty PHP.
Serwerek o którym mówię ma wykonywać prostsze funkcje:
1. Gromadzić w jednym miejscu dane z kilku rozproszonych czujników i sterowników.
2. Konwertować dane z formatów wygodnych dla AVR-ów na te czytelne dla człowieka (np. int na float).
3. Przygotowywać proste raporty, co znów wiąże się z powyższą konwersją. Na przykład zamiast "+TEMP: 255" będzie udostępniał treść "Temperatura: 25,5 st. C".
4. Dzięki serwerkowi z zewnątrz cały system będzie widoczny jako jedno urządzenie. Na razie mam tylko dwa czujniki, ale prawdopodobnie za jakiś czas dodam jeszcze kilka innych urządzeń (np. sterowanie światłem). Wtedy np. nie będę musiał zastanawiać się do którego kontrolera powinienem wysłać komendę. To będzie ustalone w konfiguracji programu i on już sam przekieruje odpowiednie polecenie tam, gdzie trzeba.

Czyli innymi słowy całość ma pracować na kilku warstwach:
1) Najniższa - zbieranie danych i wykonywanie poleceń. Ta część jest wykonywana bezpośrednio przez sterowniki zbudowane na uC. Nie wymagają one do pracy warstw wyższych i w razie konieczności można się z każdym z nich z osobna niezależnie skontaktować przez telnet albo pakiet UDP.
2) Warstwa pośrednia - pośrednicząca w komunikacji między warstwą najniższa i najwyższą. Tę funkcję spełnia omawiany daemon, odpalony na RasPi (na razie, w przyszłości pewnie na czymś lepszym). Jej funkcją jest gromadzenie danych ze wszystkich czujników i przekazywanie ich wyżej, tudzież rozsyłanie niżej poleceń przychodzących od użytkownika. Na tej warstwie odpalona jest także automatyka. Np. sprawdzamy, czy określona wartość na dwóch lub więcej czujnikach wzrosła ponad ustalony stan - jeśli tak, wysyłamy maila.
3) Warstwa najwyższa - strona WWW z PHP albo aplikacja na Androida. :)

BTW rzuć okiem na moją wcześniejszą wypowiedź - edytowałem ją. Mam kilka pytań odnośnie alarmów.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 13:00 
Offline
Użytkownik

Dołączył(a): 05 lut 2013
Posty: 302
Pomógł: 19

Nie rozpedzajcie sie ;)
Autor watku niech lepiej malymi kroczkami zacznie sobie opanowywac technologie.
Sugerowalbym:

- serwer w C do odbioru danych (zeby przetrenowac forki i czytanie z socketow)
- AVR jako klient
- UDP bym wywalil i przeszedl na TCP
- serwer mialby wejscia: odbior danych z AVR (socket TCP), zarzadzanie przez socket TCP albo unix socket (druga faza)

Opanowanie fork, obsluga TCP dla kogos kto ogarnia C to pare dni/pare godzin zalezy ile ma czasu dziennie na nauke.

Takie cwiczenie daje fajna baze wiedzy o systemie, troche o protokolach sieciowych ale przyszlosciowo niestety nie jest najlepszym rozwiazaniem, bo za chwile moze sie okazac ze bedzie potrzebna baza danych, cos do rysowania wykresow, jakiegos gui do zarzadzania.
Mimo tych wad POLECAM pojsc droga zbudowania w pelni dzialajacego obslugujacego wiele polaczen naraz serwera TCP.
Google twoim przyjacielem, jest na pewno tez pare ksiazek o pisaniu na linuxa. A i na forum paru specow jak widac jest :)

------------------------ [ Dodano po: 2 minutach ]

Co do alarmow to nic nie stoi na przeszkodzie zrobienie jak na AVR:

- jeden alarm liczacy (mili)sekundy
- w petli glownej sprawdzasz wartosc licznika i uruchamiasz funkcje wtedy kiedy potrzebujesz



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 13:27 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

charsz napisał(a):
Autor watku niech lepiej malymi kroczkami zacznie sobie opanowywac technologie.


Dokładnie właśnie to mam na myśli. Opis całego systemu to tylko ogólna wizja tego, co kiedyś chciałbym osiągnąć. Na razie jestem na etapie tworzenia poszczególnych "cegiełek" w ramach samokształcenia. Mam już parę czujników, takich jak TUTAJ. Teraz jestem na etapie pisania daemona na RasPi, który będzie pośredniczył w komunikacji i odpowiadał za parę podstawowych funkcji z zakresu automatyki. Potem napiszę jakiś Prosty skrypt, który da mi dostęp do aktualnych odczytów przez WWW. W międzyczasie może skonstruuję jeszcze jakiś sterownik, który podłączę do tego systemu.

Plany co do bardziej skomplikowanego WebUI albo aplikacji na Androida, to znacznie odleglejsza przyszłość. :)

Cytuj:
- serwer w C do odbioru danych (zeby przetrenowac forki i czytanie z socketow)
- AVR jako klient
- UDP bym wywalil i przeszedl na TCP


Ja to widzę trochę inaczej. Po pierwsze nie mam zamiaru rezygnować z UDP. Nie widzę powodu, dla którego miałbym męczyć niewielki uC sesją TCP. Po drugie najprostszy stos na AVR-y (Tuxgraphics) ma na tyle ograniczone możliwości w zakresie komunikacji TCP, że przewaga nad UDP jest znikoma.
Inaczej też widzę kierunek komunikacji w tym przypadku. Wolę, żeby to AVR był serwerem i wysyłał odpowiedź po otrzymaniu odpowiedniego requesta. Daemon na RasPi w tym wypadku pełnił będzie funkcję klienta UDP, cyklicznie odpytując o nowe dane. Takie podejście ma kilka zalet:
1) W razie awarii RasPi ciągle mam możliwość ręcznego odczytania każdego czujnika, chociażby za pomocą netcata albo PacketSendera.
2) Mogę łatwo ustalić częstotliwość odświeżania danych.

Tak więc daemon będzie klientem UDP dla czujników na AVR-ach, a także serwerem TCP dla wyższej warstwy.



Cytuj:
Opanowanie fork, obsluga TCP dla kogos kto ogarnia C to pare dni/pare godzin zalezy ile ma czasu dziennie na nauke.


Na chwilę obecną nie mam większych problemów z obsługą klienta UDP i TCP w C. Podpierając się przykładami z Sieci napisałem już funkcję odczytującą dane z czujnika. Wygląda ona następująco:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Z klientem TCP miałem do czynienia podczas innego ćwiczenia - napisałem prosty program, który komunikuje się z serwerem MPD, parsuje dane o aktualnie odtwarzanej muzyce i wyświetla takie informacje jak tytuł czy wykonawca na wyświetlaczu 2x16 (podpiętym do RasPi).
Cytuj:

Takie cwiczenie daje fajna baze wiedzy o systemie, troche o protokolach sieciowych ale przyszlosciowo niestety nie jest najlepszym rozwiazaniem, bo za chwile moze sie okazac ze bedzie potrzebna baza danych, cos do rysowania wykresow, jakiegos gui do zarzadzania.


Jedno nie wyklucza drugiego. Bazę danych będzie można w przyszłości podpiąć do tego daemona, a GUI czy rysowaniem wykresów niech się już zajmie skomunikowana z nim wyższa warstwa (webaplikacja, aplikacja na androida itp.).


Cytuj:
Co do alarmow to nic nie stoi na przeszkodzie zrobienie jak na AVR:

- jeden alarm liczacy (mili)sekundy
- w petli glownej sprawdzasz wartosc licznika i uruchamiasz funkcje wtedy kiedy potrzebujesz


Tak robiłem to do tej pory. Czyli to jest prawidłowe podejście?
Nie ma pod Linuksem jakiegoś rozwiązania, które pozwalałoby to zrobić o wiele prościej, np. rejestrując wiele funkcji,. które mają się wykonywać w różnych odstępach czasu?


mokrowski napisał(a):
A, i jeśli możesz, zrezygnuj z UDP. UDP jest protokołem bez potwierdzeń i zawodnym i będziesz zdziwiony że jak coś włączysz... to się nie włączyło :-)


W moim przypadku nie jest to żadnym problemem. Po pierwsze do tej pory jeszcze ani razu mi się nie zdarzyło, żeby jakiś pakiet nie dotarł.
Po drugie po stronie AVR soft napisany jest w taki sposób, by po wykonaniu operacji zawsze była odsyłana odpowiedź z informacją o stanie po wykonaniu tej operacji. Jeśli nie dostanie się informacji zwrotnej wiadomo, że operację trzeba powtórzyć.

Cytuj:
Proponuję zacząć pisać bo jak pytałeś o timery, to jeszcze kawałek drogi przed tobą :-)


Na razie nic nie stoi na przeszkodzie, żeby robić to na timerach, tak jak w AVR?
To też jest dobre podejście?

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Tylko czy takie podejście nie będzie przeszkodą w obsłudze serwera TCP?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 14:49 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

mokrowski napisał(a):

Nie zgadzam się co do Twojego wyboru UDP zamiast TCP ale to Ty wiesz więcej o swoim projekcie a ja bazuję jedynie na tym co napisałeś. Informuję że są inne stosy TCP/UDP (np. contiki). Tu nie będę polemizował.


Wydaje mi się, że źle się zrozumieliśmy. Ja nie odrzucam komunikacji po TCP jako takiej. Uważam jedynie, że nie ma sensu przerabiać gotowego projektu licznika Geigera (z paroma innymi czujnikami na pokładzie), ponieważ wymagałoby to zastosowania innego stosu. W tym przypadku UDP sprawdza się znakomicie, a wady tego rozwiązania nie stwarzają wielkiego problemu - co najwyżej jeden request na pół roku nie dojdzie do skutku z uwagi na zagubiony pakiet.

W przyszłych projektach mogę już jednak zastosować zupełnie inne podejście. Tak naprawę mam zamiar przyjrzeć się któremuś z lepszych stosów (uC, może nawet lwIP po lepszym zapoznaniu się z STM-ami). Obecnie także zainteresowałem się układami W5100/W5500, które mają wbudowany stos. Projektuje właśnie płytkę z jednym z nich, gdy będzie gotowa raczej nie będę "marnował" możliwości tego sprzętu na UDP. ;)

Tyle tylko, że to już będzie osobne urządzenie, ze swoją własną strukturą i osobną funkcją odczytu stanu. Równie dobrze będę mógł w niej zastosować klienta TCP, niezależnie od dotychczasowej funkcji, posługującej się UDP.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 15:35 
Offline
Użytkownik

Dołączył(a): 05 lut 2013
Posty: 302
Pomógł: 19

No to od czego zaczynamy? Klienta UDP juz masz jak widze, zapisywanie do pliku ?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 19:08 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

charsz napisał(a):
No to od czego zaczynamy? Klienta UDP juz masz jak widze, zapisywanie do pliku ?


Z tym sobie jakoś poradzę. Ta część chyba nie różni się aż tak znacznie od sposobu obsługi systemu plików na AVR-ach z kartą pamięci.

Nie do końca w tej chwili radzę sobie jeszcze ze zrozumieniem forkowania procesów w związku z obsługą serwera TCP (niby już coś takiego robiłem pisząc daemona, ale wówczas opierałem się na gotowym przykładzie) i wykonywaniem określonych funkcji w zadanych odstępach czasu. Będę musiał trochę doczytać...

BTW jaki jest najprostszy/najlepszy sposób na wysłanie maila z poziomu programu napisanego w C pod Linuskem?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 sie 2014, o 08:16 
Offline
Użytkownik

Dołączył(a): 05 lut 2013
Posty: 302
Pomógł: 19

To w koncu piszesz serwer TCP?

Najprostszy sposob na wyslanie maila to odpalenie klienta poczty przez exec/system.
Albo wykonanie polaczenia na port 25 i nadawanie protokolem SMTP.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 sie 2014, o 11:30 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

charsz napisał(a):
To w koncu piszesz serwer TCP?


Czytam przykłady w sieci. Chciałbym zapytać, czy dobrze to wszystko rozumiem.

Weźmy fragment takiego kodu:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jak rozumiem po wywołaniu funkcji fork program rozwidla się - zostaje niejako zduplikowany i normalnie obydwa procesy wykonywałyby dokładnie to samo zadanie. Dalej jednak mogę sprawdzić w którym z procesów się znajduję, za pomocą instrukcji warunkowej, sprawdzając wartość zwróconą wcześniej przez fork(). Jeśli jest ona równa 0, znajduję się w procesie "rodzicu". Jeśli nie - w potomnym. Tutaj mogę zadecydować jakie instrukcje będą wykonywane przez każdy proces. Jeden z nich po prostu zamyka własną kopię socketa sieciowego, drugi zajmuje się udzieleniem odpowiedzi na zapytanie z sieci. Po wykonaniu tej operacji zostaje zamknięty funkcją exit(0);

Mam jednak kilka pytań:
1) Przede wszystkim czy nie lepiej (bardziej intuicyjnie) byłoby zamienić te funkcje miejscami, żeby utrzymywanie komunikacji odbywało się w procesie potomnym?
2) Co ze współdzieleniem danych? Jeśli proces potomny zapisuje dane do jakiegoś bufora, albo zwraca wynik do zmiennej, to czy główny proces będzie miał dostęp do tych informacji.
3) Nic nie stoi na przeszkodzie, żeby "rozwidlić" proces na samym początku pętli main i w każdym z wariantów ustawić dwa osobne zadania z dwiema osobnymi nieskończonymi pętlami? W jednej na przykład można by zainicjować i obsługiwać serwer (jak wyżej) a w drugiej realizować inne zadania, np. cykliczne odczytywanie czujników i wysyłanie raportów.
4) Czy operacja opisana powyżej w jakiś wymusi jakiś inny sposób forkowania następnych procesów? Na przekład trzeba będzie spodziewać się innych wartości zmiennej pid? To samo pytanie mam też odnośnie operacji "daemonizacji" programu.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 sie 2014, o 13:11 
Offline
Użytkownik

Dołączył(a): 05 lut 2013
Posty: 302
Pomógł: 19

Proces nadrzedny jest procesem nasluchujaco kontrolnym a proces podrzedny jest procesem wykonawczym.
Cytuj:
1) Przede wszystkim czy nie lepiej (bardziej intuicyjnie) byłoby zamienić te funkcje miejscami, żeby utrzymywanie komunikacji odbywało się w procesie potomnym?

nie, proces nadrzedny jest jeden, procesow potomnych moze byc dziesiatki.
Sprobuj cos takiego uruchomic,
zrob 'ps -aux'
pozniej zrob polaczenie na port nasluchujacy
i znow zrob 'ps -aux'
bedziesz mial jeden proces wiecej,
jesli przetwarzanie (doprocessing()) bedzie odpowiednio dlugie to mozesz otworzyc kolejna sesje i zobaczysz ze pojawi sie kolejny proces na liscie procesow.
Chodzi o to, ze gdyby twoje czujniki byly klientami TCP to nie musialbys sie martwic ze dwa naraz zaczna pisac. Program nadrzedny z forkuje sie tyle razy ile potrzeba.

Cytuj:
2) Co ze współdzieleniem danych? Jeśli proces potomny zapisuje dane do jakiegoś bufora, albo zwraca wynik do zmiennej, to czy główny proces będzie miał dostęp do tych informacji.


O ile dobrze pamietam, to nie ma od tak sobie wspoldzielenia pamieci miedzy procesami. Opcji na polaczenia miedzy procesami jest wiele:
IPC, kolejki, komunikacja socketami, i pamiec wspoldzielona - ale wszystko trzeba samemu oprogramowac.

Cytuj:
3) Nic nie stoi na przeszkodzie, żeby "rozwidlić" proces na samym początku pętli main i w każdym z wariantów ustawić dwa osobne zadania z dwiema osobnymi nieskończonymi pętlami? W jednej na przykład można by zainicjować i obsługiwać serwer (jak wyżej) a w drugiej realizować inne zadania, np. cykliczne odczytywanie czujników i wysyłanie raportów.

Pytanie czy potrzebujesz takiego rozwidlenia. Pamietaj o punkcie nr 2 - wspoldzielenie danych. Wiekszosc mechanizmow wspoldzielenia nie wymaga zeby procesy mialy tego samego ojca.

Cytuj:
4) Czy operacja opisana powyżej w jakiś wymusi jakiś inny sposób forkowania następnych procesów? Na przekład trzeba będzie spodziewać się innych wartości zmiennej pid? To samo pytanie mam też odnośnie operacji "daemonizacji" programu.


Jesli bedziesz uzywal fork to nie, jesli zdecydujesz sie uzyc rfork bedziesz mogl spodziewac sie czegos innego:
wiecej tu: http://plan9.bell-labs.com/magic/man2html/2/fork



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 sie 2014, o 14:27 
Offline
Użytkownik

Dołączył(a): 05 gru 2013
Posty: 246
Pomógł: 0

charsz napisał(a):
nie, proces nadrzedny jest jeden, procesow potomnych moze byc dziesiatki.
Sprobuj cos takiego uruchomic,


Przepraszam za poprzednie pytanie, najwyraźniej coś mi się pomieszało. Myślałem, że pid równy 0 odpowiada procesowi nadrzędnemu, a nie potomnemu.

Tak swoją drogą dlaczego zamykanie socketa newsockfd odbywa się w procesie nadrzędnym? Nie lepiej byłoby go zakończyć po zakończeniu wszystkich operacji przez proces potomny, obsługujący dane połączenie?

Cytuj:
O ile dobrze pamietam, to nie ma od tak sobie wspoldzielenia pamieci miedzy procesami. Opcji na polaczenia miedzy procesami jest wiele:
IPC, kolejki, komunikacja socketami, i pamiec wspoldzielona - ale wszystko trzeba samemu oprogramowac.


Ok, poczytam. Czyli w każdym razie jeśli program zawierający jakieś zmienne globalne zostanie sforkowany, to każdy z procesów będzie dysponował własną kopią zmiennych? Czy w związku z tym tablice i struktury przeznaczone dla konkretnego procesu powinienem tworzyć wewnątrz "ifa", już po wykonaniu fork()?

W każdym razie w oparciu o podany wcześniej przykład przygotowałem prosty echo-serwer.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Działa, jednak mam kilka pytań. Przede wszystkim czy instrukcje "listen(sockfd,5)" i "clilen = sizeof(cli_addr)" nie powinny się znaleźć wewnątrz pętli while, tak aby były wykonywane po zakończeniu każdego kolejnego połączenia?
Po drugie gdzie powinno się zamknąć sockfd? Standardowo, na końcu funkcji main(), za pętlą while(1)? Tej instrukcji tutaj brakuje...



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 sie 2014, o 15:00 
Offline
Użytkownik

Dołączył(a): 05 lut 2013
Posty: 302
Pomógł: 19

Cytuj:
Tak swoją drogą dlaczego zamykanie socketa newsockfd odbywa się w procesie nadrzędnym? Nie lepiej byłoby go zakończyć po zakończeniu wszystkich operacji przez proces potomny, obsługujący dane połączenie?

Odpowiedz na to jest w linku ktory podalem.

Cytuj:
Po drugie gdzie powinno się zamknąć sockfd? Standardowo, na końcu funkcji main(), za pętlą while(1)? Tej instrukcji tutaj brakuje...

Ja tam widze zamkniecie sockfd w lini 60.

Owszem brakuje w przykladzie zamkniecia kopii sockfd w glownym procesie, ale poniewaz z niego inaczej niz zabijajac proces nie wyjdziesz to w tej chwili poprawnym zamknieciem socketow bedzie musial zajac sie system.
Zeby wyjsc poprawnie musialbys dodac obsluge sygnalow.


Cytuj:
Przede wszystkim czy instrukcje "listen(sockfd,5)" i "clilen = sizeof(cli_addr)" nie powinny się znaleźć wewnątrz pętli while, tak aby były wykonywane po zakończeniu każdego kolejnego połączenia?

Proponuje debuger albo printfy na console zeby zobaczyc co sie dzieje.
Albo dokladnie poczytanie co robi listen a co robi accept.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 16 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
cron
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO