init FPRWKH72QEP6XQFDMUYVZG76U277PWJOYIDZJHQ





Proces Init





Do spisu tresci tematu 10.






10.4 Proces init

Spis tresci





Wprowadzenie.

Czym zajmuje sie proces init?

Algorytm inita.

Opis pliku /etc/inittab

Struktura danych: CHILD

Przykladowy plik /etc/inittab


Bibliografia










10.4.1 Wprowadzenie





Przedostatnia instrukcja w funkcji "start_kernel()" uruchamianej
przy inicjalizacji systemu jest powolanie nowego procesu, procesu o identyfikatorze
1, zwanym powszechnie procesem init. Proces ten bedac caly czas w trybie
jadra uruchamia dwa demony. Pierwszy do obslugi swap'a, drugi do opoznionego
zapisu buforow na dysk. Nastepnie wywoluje funkcje setup(), ktora inicjalizuje
urzadzenia i podmontowywuje do korzenia glowny system plikow. Otwiera terminal
i ustawia na niego swoje stdin, stdout i stderr. Nastepnie wykonuje po
kolei exec("/etc/init"); exec("/bin/init");exec("/sbin/init").
Jezeli zaden sie nie udal, to proces init przechodzi do nieskonczonej petli,
w ktorej: 1. uruchamia shell 2. czeka na jego zakonczenie.
Przypadek, w ktorym nie udalo sie uruchomic zadnego inita jest malo ciekawy,
dlatego zajmiemy sie teraz przypadkiem, w ktorym nam sie to udalo.
Wersji "initow" jest dosyc duzo, wiecej niz wersji jadra. Zwiazane
jest to z tym, ze program init nie nalezy juz do kodu jadra, jest on zwyklym
programem, dzialajacym w trybie uzytkownika, tyle ze z identyfikatorem
root'a. Kazdy moze latwo go sobie zmienic na inny bez zmieniania jadra,
wystarczy dotychczasowy program init, ktory jest w jednym z katalogow /etc,
/bin lub /sbin, zamienic na nowy o takiej samej nazwie.
Ostatnio standardem staje sie init Systemu V, dlatego dzialanie procesu
init opisze na jego przykladzie.







10.4.2 Czym zajmuje sie
proces init.




Prace procesu init mozemy podzielic na dwie czesci. Pierwsza, ktora
jest wykonywana podczas ladowania systemu, polega na wczytaniu pliku /etc/inittab
i uruchomieniu procesow zwiazanych z inicjacja systemu, wczytaniu poziomu
dzialania (ang. runlevel) i uruchomieniu procesow zwiazanych z tym poziomem.
Druga czesc to nadzorowanie pracy systemu. Praca ta polega na wznawianiu
procesow, ktorych akcja zdefiniowana w inittabie bylo "respawn"
, na przechwytywaniu sygnalow o zakloceniach zasilania i na uruchamianiu
zwiazanych z nimi procesow; oraz na przejsciu na nowy poziom dzialania
na zyczenie administratora. Przejscie to wiaze sie z zabiciem procesow,
ktore nie sa powiazane z nowym poziomem, i uruchomieniem tych, ktore sa
powiazane.







10.4.3 Krotki opis algorytmu
init.




algorytm init 
wejscie: brak
wyjscie: brak

{


Ustaw obsluge sygnalow;
runlevel="sysinit"; /* runlevel jest zmienna globalna,
na ktorej mamy aktualny poziom dzialania */
Przeczytaj plik /etc/inittab;
Sprawdz, czy sa dzieci, ktore nalezaloby uruchomic;
/* w praktyce sprowadza sie to do uruchomienia procesow o akcji "sysinit"
*/
for ever /*glowna petla*/
{


Sprawdz, czy nie nalezy zmienic poziomu dzialania;
/* Poziom jest zmieniany tylko podczas inicjacji systemu, oraz po zakonczeniu
wszystkich procesow-dzieci w poziomie dla jednego uzytkownika */
if (sa procesy, na ktorych zakonczenie czekamy i nie ma nieobsluzonych
sygnalow) pause();
/* pause() powoduje uspienie procesu do czasu otrzymania jakiegokolwiek
sygnalu */
Sprawdz, czy mozna juz uruchomic dzieci, ktorych nie udalo
sie wznowic wczesniej;
Przetworz sygnaly;
Sprawdz, czy sa dzieci, ktore nalezaloby uruchomic;
sync(); /* zapisuje bufory na dysk */


}


} / * init */








10.4.4 Opis pliku /etc/inittab.





Kazda linia w tym pliku ma format: id:runlevels:action:process

id to niepowtarzalny dwuliterowy identyfikator linii, runlevels to poziomy,
przy ktorych ma byc wykonana dana akcja, action okresla wlasnie te akcje,
a process jest linia komendy, jaka ma byc wykonana.
Mamy zdefiniowane nastepujace akcje:


respawn - proces bedzie kazdorazowo wznowiony po zakonczeniu

wait - proces bedzie rozpoczety tylko raz przy rozpoczeciu poziomu
wykonania okreslonego przez runlevels, i proces init bedzie czekal na jego
zakonczenie

once - tak, jak wyzej, tylko nie bedziemy czekac na jego zakonczenie

boot - proces bedzie rozpoczety raz, podczas przejscia do poziomu
"boot"

bootwait - jak wyzej, tyle ze bedziemy czekac na jego zakonczenie

sysinit - proces bedzie rozpoczety raz, podczas przejscia do
poziomu "sysinit"

powerwait - proces bedzie rozpoczety, jesli init otrzyma sygnal
SIGPWR , mowiacy o jakichs problemach z zasilaniem, i bedziemy czekac na
jego zakonczenie

power - tak jak wyzej, tylko nie czekamy na jego zakonczenie

powerokwait - proces bedzie rozpoczety, jesli init otrzyma sygnal
SIGPWR, i w pliku /etc/powerstatus bedzie slowo "OK" , co oznacza,
ze zasilanie powrocilo. Init bedzie czekal na jego zakonczenie

ctraltdel - proces bedzie rozpoczety po nacisnieciu ctrl+alt+del

initdefault - okresla poziom, do jakiego init ma przejsc po
skonczeniu inicjacji systemu


Pole runlevels dla akcji boot, bootwait, sysinit, initdefault jest ignorowane.

Jezeli chodzi o znaczenie poziomow dzialania, standartowo 's' oznacza poziom
dla jednego uzytkownika, 1,2,3,4,5,6 poziomy wieloztkownikowe, przy czym
6 to poziom dla X-windows. Poziom 0 to zamkniecie systemu. Podkereslam,
ze jest to standartowe ustawinie, tak na prawde to znaczenie ich definiuja
procesy jakie sa przy nich uruchamiane. Standartowy plik /etc/inittab jest
przedstawiony tutaj. Ale kazady
moze zamienic go sobie jak chce i wetedy te poziomy moga miec zupelnie
inne znaczenie.

Krotko o kolejnosci wykonywania procesow podczas inicjalizowania systemu:
Pierwszym poziomem dzialania po rozpoczeciu pracy inita jest sysinit. Potem
uruchamiamy procesy, ktorych akcja jest wlasnie "sysinit" i czekamy
na ich zakonczenie .Nastepnie sprawdzamy, jaki ma byc docelowy poziom;
sprawdzenia tego dokonuje funkcja "GetInitDefault".
Jesli tym poziomem jest tryb dla jednego uzytkownika (ang. single user
mode), to po zakonczeniu poziomu sysinit od razu do niego przechodzimy,
wpp po sysinit, a przed poziomem docelowym mamy jeszcze poziom "boot".
W tym poziomie odpalamy procesy, ktorych akcja jest "boot" lub
"bootwait". Po zakonczeniu procesow o akcji "bootwait"
przechodzimy juz do docelowego poziomu. Zmiana poziomow zajmuje sie funkcja
"BootTransitions " .
Procesy o akcji "boot" to jedyne procesy, ktore moga dzialac
we wszystkich poziomach, reszta moze dzialac tylko w poziomach okreslonych
przez "runlevels".

algorytm: GetInitDefault;
wejscie: brak;
wyjscie: brak;
{


Sprawdz, czy w pliku inittab byla linijka o akcji "initdefault";
If (byla taka linijka) return( poziom, jaki ona definiowala);
Spytaj administratora, jaki ma byc poziom dzialania;
return ( odpowiedz administratora );


} /* GetInitDefalut */









10.4.5 CHILD






Najwazniejsza struktura danych w programie init jest CHILD; Opisuje
ona kazde polecenie wczytane z inittaba oraz ewentualny proces z nim zwiazany.

struct CHILD {
int flags ; ---------/* informacje o statucie dzialania procesu */
int extsta; --------/* kod wyjscia procesu */
int pid; -----------/* identyfikator procesu, lub zero jesli nie jest uruchomiony
*/
time_t tm; --------/* czas ostatniego wznowienia */
int count; ---------/* liczba wznowien w ostatnich
TESTTIME sekundach */
char id[8]; ---------/* pole id z inittaba tego polecenia */
char[12];----------/* poziomy, przy ktorych moze dzialac ten proces */
int action; ---------/* akcja */
char process[128]; ---/* linia komendy, jaka nalezy wykonac */
CHILD * new; ------/* pole to jest wykorzystywane przy ponownym czytaniu
inittaba do zaznaczenia procesow, ktore sie powtarzaja */
CHILD * next; -----/* wskaznik na nastepny element listy dzieci */
} /* CHILD */
Mamy zdefiniowane jeszcze trzy stale zwiazane z wykonywaniem procesow:

define MAXSPAWN /* okresla maksymalna liczbe wznowien procesu w przeciagu
... */
define TESTTIME /* tylu sekund */
define SLEEPTIME /* w przypadku przekroczenia liczby
wznowien, czas, jaki musi minac, aby ponownie init probowal uruchomic ten
proces */

dygresja: W inicie, ktory opisuje, powyzsze stale sa zdefiniowane nastepujaco
(10, 120, 300). Wystarczy wiec w przeciagu dwoch minut zalogowac sie i
wylogowac, zeby zablokowac terminal na 5 minut.

Jezeli chodzi o flagi w strukturze CHILD to mamy:


RUNNING - proces wlasnie sie wykonuje

KILLME - nalezy zabic ten proces

FAILING - przekroczono maksymalna liczbe wznowien tego dziecka
i nalezy odczekac przed ponownym jego wznowieniem

WAITING - czekamy na zakonczenie tego procesu

XECUTED - dziecko bylo juz kiedys rozpoczete; jezeli chodzi
o te flage, to jej ustawienie nie zawsze jest zgodne z prawda, tzn. jest
ustawiona nawet wtedy, jesli proces nie byl nigdy rozpoczety. Dotyczy to
procesow o akcji zwiazanej z obsluga problemow zwiazanych z napieciem,
i o akcji ctraltdel. Tym procesom te flage ustawia sie na poczatku, mimo
ze sie ich nie rozpoczyna. Takie ustawienie pomaga potem zaimplementowac
uruchamianie procesow.



Za dziecko uwazam zatem strukture, ktora powyzej przedstawilem, a nieraz
takze proces z nia zwiazany ( jedynym wyjatkiem jest obsluga sygnalu SIGCHLD;
tam pod pojeciem dziecko kryje sie proces, ktorego identyfikatorem ojca
jest liczba 1( czyli dziecko w ujeciu Unixa)). Wiem, ze nie jest to najlepsze
rozwiazanie, ale niestety nie wpadlem na lepsze, poza tym w kodzie tez
bylo to tak nazwane (za przyklad daje nazwe struktury), tych, ktorych przyjecie
takiej terminologii wprowadzilo w blad, z gory przepraszam.Pod pojeciem
"proces" kryje sie zwykle "proces zwiazany z danym dzieckiem".







Czytanie pliku/etc/inittab;




Zadanie to wykonuje funkcja ReadItab(). Jest ona wywolywana przy rozpoczeciu
pracy przez inita, oraz przy przejsciu do innego poziomu dzialania.

algorytm: ReadItab
wejscie: brak;
wyjscie: brak;
{


while(nie przeczytales calego pliku){



Przeczytaj linie i sprawdz, czy jest poprawna;
if (jest poprawna){


Przydziel pamiec dla struktury CHILD i zainicjuj
ja;
Dodaj to dziecko do listy dzieci;
/* procesy zwiazane z obsluga problemow z napieciem, umieszcza sie na poczatku
listy, natomiast pozostale na koncu */


};


};
if (bylo to ponowne czytanie inittaba){ /* oznacza to, ze przechodzimy
na nowy poziom dzialania na polecenie administratora */

Zabij dzieci, ktore nie powinny dzialac na nowym poziomie.
/*Zabijamy wszystkie procesy, ktorych nie ma w nowo przeczytanym inittabie,
tzn. nie ma linijki z identyfikatorem, ktory odpowiadalby polu "id"
w strukturze CHILD danego procesu. Zabijamy takze procesy, ktore sa w nowoprzeczytanym
inittabie, ale pole "rlevel" ich struktury CHILD nie zawiera
poziomu, na ktory sie przelaczamy, wyjatkiem sa procesy o akcji "boot",
one moga dzialac zawsze. */


}; /* ReadItab */



Sprawdzeniem, czy nie nalezy przejsc do innego
poziomu zajmuje sie funkcja "BootTransitions()" . Jest
ona wywolywana przy kazdym obrocie petli glownej, ale zmiany poziomu dokonuja
sie znacznie rzadziej( przy inicjalizowaniu systemu oraz po zakonczeniu
wszystkich naszych dzieci przy pracy na poziomie dla jednego uzytkownika
).
algortym: BootTransitions;
wejscie: brak;
wyjscie: brak;
{


for( kazde dziecko ) if ( dziecko dziala i jego akcja nie jest boot
) return; /* nie mozemy zmienic poziomu*/
if ( aktualny poziom to "sysinit"){


log_level=GetInitDefault(); /* zmienna
"log_level" jest statyczna */
if (log_level=='s') /* od razu przechodzimy do decelowego poziomu */ {


runlevel = 's'
return:


}
else /* najpierw poziom boot */{


runlevel = 'boot';
renturn;



}


} /* poziomom sysinit */;
if ( aktualnym poziomem jest boot ) runlevel=log_level; /* wartosc wczytana
poprzednio przez "GetInitDefault"
*/
if ( aktualnym poziomem jest 's') {


runlevel=GetInitDefault();
Odwies flagi (RUNNIGN, XECUTED, WAITING) dzieciom zwiazanym z poziomem
's'; /* tzn. tym, ktorych pole rlevel ich struktury CHILD
zawiera 's' */


}


} /* BootTransitions */






Obsluga sygnalow:




Proces init obsluguje sygnaly dwuetapowo. Pierwszy etap polega na zaznaczeniu
na zmiennej globalnej "got_signlas" sygnalu, ktory przyszedl.
Etap ten jest obslugiwany przez funkcje "signal_handler", ktora
przechwytuje prawie wszystkie sygnaly. Wyjatkiem jest sygnal SIGCHLD (sygnal
ten jest wysylany w przypadku smierci jakiegos naszego dziecka), ktory
jest obslugiwany przez "chld_handler". Funkcja ta oprocz ustawienia
odpowiedniego bitu w "got_signals" sprawdza ktore to bylo dziecko,
i jesli byl to proces z inittaba to ustawia w jego strukturze CHILD
flage ZOMBIE. Drugim, zasadniczym etapem przetwarzania sygnalu jest
wykonanie zadan odpowiadajacych danemu sygnalowi. Etapem tym zajmuje sie
funkcja "ProcessSignals".

algortym Ustawienie przechwytywania sygnalow;
wejscie: brak;
wyjscie: brak:
{


Powiadom jadro, ze chcemy otrzymac sygnal SIGINT, jesli zostalo nacisniete
ctrl+alt+del;
Ustaw przechwycenie sygnalu SIGCHLD przez funkcje "chld_handler";
Ustaw przechwycenie reszty sygnalow przez funkcje "signal_handlers";


};

Przetwarzaniem sygnalow zajmuje sie funkcja "ProcessSignals".
Funkcja ta jest wywolywana przy kazdym obrocie petli
glownej.

algorytm: ProcessSignals;
wejscie: brak;
wyjscie: brak:
{


if( przechwycilismy SIGPWR){ /*mamy jakies problemy z zasilaniem*/


Przeczytaj z pliku /etc/powerstatus co sie dzieje;
Odwies flagi XECUTED tym procesom, ktore sa zwiazane z tym zdarzeniem;
/* Odwieszenie tej flagi spowoduje, ze przy najblizszym wywolaniu funkcji
"StartEmIfNeeded" procesy te zostana uruchomione*/
Usun sygnal SIGPWR ze zmiennej "got_signlas";


};
if (przechwycilismy SIGINT) { /* nacisnieto ctr+alt+del*/


Odwies flage XECUTED procesom, ktorych akcja jest ctrlaltdel; /* skutek,
patrz wyzej */
Usun sygnal SIGINT ze zmiennej "got_signlas";


};
if (przechwycilismy SIGCHLD) { /* wlasnie umarlo jakies nasze dziecko*/


Odwies flagi RUNNING, WAIT, ZOMBIE , procesom, ktore maja ustawiona
flage ZOMBIE.
/* flage te ustawiala funkcja "chld_handler" */
/* odwieszenie tych flag bedzie potem wykorzystywane przez funkcje "StartEmIfNeeded"*/
Usun sygnal SIGCHLD ze zmiennej "got_signlas";


};
if ( przechwycilismy SIGHUP) { /*zmiana poziomu dzialania*/


Przeczytaj z pliku /etc/initrunlevel, jaki ma byc nowy poziom;
Przeczytaj plik /etc/inittab; /* dziala inaczej niz za pierwszym czytaniem
*/
Usun sygnal SIGHUP ze zmiennej "got_signlas";


};


};/ * ProcessSignals*/


Sprawdzeniem, czy sa procesy, ktore nalezaloby
uruchomic, zajmuje sie funkcja "StartEmIfNeeded".
algorytm: StartEmIfNeeded;
wejscie: brak;
wyjscie: brak;
{


for(kazde dziecko){


if ( czekamy na zakonczenie tego procesu) break;
if ( ten proces jest uruchomiony) continue;
if ( ten proces moze dzialac w aktualnym poziomie dzialania) StartUp(dziecko);


};


}; /* StartEmIfNeeded */

Funkcja StartUp sprawdza czy dane dziecko nalezy uruchomic, jesli tak
to wywoluje funkce Spawn.

algorytm: StartUp;
wejscie: dziecko, ktore nalezy sprawdzic, czy nie nalezy go uruchomic;
wyjscie: brak;
{


if (to dziecko przekroczylo maksymalna liczbe wznowien w ostatnim czasie)
return;
switch(akcja dziecka){


case SYSINIT: case BOOTWAIT: case WAIT: case POWERWAIT:
case CTRALTDEL: case POWEROKWAIT:
if ( jeszcz nie bylo wznawiane)/* uruchamiamy je teraz */ flags=flags|WAITING;
case BOOT: case POWERFAIL: case ONCE:
if (juz bylo uruchomione) return;
case RESPAWN:
Spawn(dziecko); /* uruchamiamy to dziecko */


};


}; /* StartUp */

algorytm: Spawn; /* Uruchom proces */
wejscie: dziecko, ktore nalezy uruchomic;
wyjscie: brak;
{


if (akcja tego dziecka jest RESPAWN) /* musimy sprawdzic, czy tym uruchomieniem
nie przekroczym maksymalnej liczyby wznowien*/




if ( wznawiamy go za czesto) { alarm(SLEEPTIME);
return};


flags|=(RUNNING|XECUTED);
Utworzy tablice argv dla tego dziecka; /* jezeli linia komend tego dziecka
zawiera jakies dziwne znaczki typu: ! $ | / < > ?, oznacza to, ze
musimy uruchomic jakiegos shella i przekazac mu linie komend jako argument.
Natomiast jesli nie zawiera, to kazdy wyraz z tej linii wpisujemy kolejno
do tablicy argv */
if ((pid =fork())==0){ /* jestesmy w procesie dziecka */


setsid() /* otwiera sesje dla tego procesu */
execvp(argv[0], argv);


}
else { /* Jestesmy w procesie ojca */


CHILD-> pid=pid;
return;


};


}; /* Spawn */

Sprawdzeniem, czy mozna juz uruchamiac procesy, ktore
przekroczyly maksymalna liczbe wznowien, zajmuje sie funkcja "FailCheck()".
Jest ona wywolywana przy kazdym obrocie glownej
petli.
algorytm: FailCheck;
wejscie: brak;
wyjscie: brak;
{


for(kazde dziecko){


if( to dziecko padlo){


if ( od ostatniego wzonwienia minelo juz SLEEPTIME
sekund ) {


CHILD->flags&=~FAILING; /* odwieszenie tej flagi spowoduje ze
przy najblizszym wywolaniu funkcji "StartEmIfNeeded"
dziecko to zostanie uruchomione */
CHILD->count=0;
CHILD->tm=aktualny_czas();


}
else alrm(CHILD->tm+SLEEPTIME-aktualny_czas()) /* sprawdzimy go potem
*/


} /* to dziecko padlo */


} /* for */


}/ * FailCheck */








10.4.6
Przykladowy plik /etc/inittab





/*Poziom do jakiego mamy przejsc po inicjalizacji systemu. */
id:5:initdefault:

/*Uruchamiamy ten skrypt przy inicjalizacji systemu (standartowo wykonuje
on polecenie '/sbin/fsck -a -A', ktore sprawdza czy wyszystkie systemy
plikow aktualnie podlaczone sa poprawne, automatycznie usuwajac napotkane
bledy ; skrypt ten podmontowywuje takze systemy plikow opisane z pliku
/etc/fstab)*/
si::sysinit:/etc/rc.d/rc.S

/* Skrypt ten uruchamiamy kiedy przechodzimy do poziomu dla jednego
uzytkownika. Standardowo odlacza on wszystkie systemy plikow i wylacza
swap'a. */
su:S:wait:/etc/rc.d/rc.K

/* Skrypt ten uruchamiamy kiedy przechodzimy do poziomu wielouzytkownikowego.
Standardowo inicjalizuje on siec, uruchamia on demona poczty, sprawdza
CD i jesli jest to podlacza je do katalogu /cdrom. */
rc:123456:wait:/etc/rc.d/rc.M

/* Trzech kroli powoduje wylaczenie komputera. */
ca::ctrlaltdel:/sbin/shutdown -t3 -rf now

/* Co robic kiedy zanika napiecie. */
pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING"


/* Jesli napiecie wraca to: */
pg:0123456:powerokwait:/sbin/shutdown -c "THE POWER IS BACK"


/* Uruchamianie odpowiedniej ilosci terminali: */
c1:12345:respawn:/sbin/agetty 38400 tty1
c2:12345:respawn:/sbin/agetty 38400 tty2
c3:45:respawn:/sbin/agetty 38400 tty3
c4:45:respawn:/sbin/agetty 38400 tty4
c5:45:respawn:/sbin/agetty 38400 tty5
c6:456:respawn:/sbin/agetty 38400 tty6

/* Poziom 6 to standardowo uruchomienie X-windows. Skrypt rc.6 wlasnie
je uruchamia */
x1:6:wait:/etc/rc.d/rc.6

/* koniec pliku /etc/inittab */






Prawda o programie init.




Tak naprawde to program init dziala troche inaczej. Sa to w zasadzie
dwa programy w jednym. Jeden jest wykonywany jezeli identyfikatorem procesu
jest liczba 1, natomiast drugi wpp. Pierwszy program to wlasnie ten, ktory
opisalem na tej stronie, natomiast drugi sluzy do powiadomienia "prawdziwego
inita", ze chcemy zmienic poziom dzialania.

algorytm: Prawdziwy init;
wejsie: Poziom, na ktory chcemy przejsc, lub brak jesli to ma byc proces
o id=1.
wyjsie: brak;
{


Pobierz identyfikator twojego procesu;
if (jest on rowny jeden) wykonaj algorytm
init
else


if (id uzytkownika jest rozny od zera) return; /* zmiany poziomu moze
dokonac tylko root */
else { /* zmieniamy poziom */


Zapisz w pliku /etc/initrunlevel jaki ma byc nowy poziom;
Wyslij do "prawdziwego inita" sygnal SIGHUP; /* Patrz obsluge
tego sygnalu przez init, tutaj */



} /* zmieniamy poziom*/


} /* else */


} /* Prawdziwy init */

Pozwolilem sobie na takie male oszustwo, zeby opis dzialania inita bylo
zgodny z opisem przedstawianym w wielu ksiazkach np Bacha, Stevensa. Mam
nadzieje, ze zostanie mi to wybaczone.









Bibliografia






Plik zrodlowy Linuxa: init/main.c

Plik zrodlowy Inita: init.c (System V init clone ver 2.64)

man



Autor: Krzysztof Micek






Wyszukiwarka

Podobne podstrony:
init
arm fir init q15?
arm fir lattice init q31? source
arm ?ft radix4 init q31?
arm fir ?cimate init q31?
arm iir lattice init ?2? source
arm lms init ?2?
arm fir ?cimate init q15? source
arm biquad ?scade ?1 init q31?
arm lms init q15? source
arm rfft init q15?
function ccvs init
arm pid init q15? source
cbq init v0 7 3
arm biquad ?scade ?1 2x64 init q31? source
arm pid init q31? source
arm ?ft radix4 init ?2? source

więcej podobnych podstron