Binciko injin Mediastreamer2 VoIP. Kashi na 11

An ɗauko kayan labarin daga nawa zen channel.

Binciko injin Mediastreamer2 VoIP. Kashi na 11

Tsarin motsi bayanai

  • Data toshe dblk_t
  • Sako mblk_t
  • Ayyuka don aiki tare da saƙonni mblk_t
  • Jerin gwano_t
  • Ayyuka don aiki tare da layin layi queue_t
  • Haɗa matattara
  • Wurin sigina na jadawali sarrafa bayanai
  • Bayan fage ayyukan ticker
  • Bufferizer (MSBufferizer)
  • Ayyuka don aiki tare da MSBufferizer

A karshe labarin mun gyara namu tace. Wannan labarin zai mayar da hankali kan tsarin ciki don motsa bayanai tsakanin matatun mai rafi na kafofin watsa labarai. Wannan zai ba ka damar rubuta nagartaccen tacewa tare da ƙarancin ƙoƙari a nan gaba.

Tsarin motsi bayanai

Ana yin motsin bayanai a cikin mai watsa labarai ta hanyar amfani da layukan da tsarin ya bayyana layi_t. Zauren sakonni kamar mblk_t, wanda su kansu ba su ƙunshi bayanan sigina ba, amma kawai hanyoyin haɗi zuwa baya, saƙo na gaba da kuma toshe bayanai. Bugu da kari, ina so in jaddada cewa akwai kuma filin hanyar haɗi zuwa saƙo mai nau'in iri ɗaya, wanda ke ba ku damar tsara jerin saƙonni guda ɗaya. Za mu kira rukunin saƙon da aka haɗa ta irin wannan jeri da tuple. Don haka, kowane sashi na jerin gwano na iya zama saƙo ɗaya mblk_t, kuma watakila shugaban sakon tuple mblk_t. Kowane saƙon tuple yana iya samun nasa toshe bayanan unguwa. Za mu tattauna dalilin da yasa ake buƙatar tuples kadan daga baya.

Kamar yadda aka ambata a sama, saƙon da kansa ba ya ƙunshi tarin bayanai, maimakon haka, yana ƙunshe da mai nuni ne kawai zuwa wurin da ake ajiyewa. A cikin wannan ɓangaren, gaba ɗaya hoton aikin mai rafi na kafofin watsa labaru yana tunawa da ɗakin ajiyar ƙofa a cikin zane mai ban dariya "Monsters, Inc.," inda kofofin (hanyoyin haɗin bayanai - ɗakunan) suna tafiya cikin mahaukacin gudu tare da masu jigilar kaya, yayin da ɗakunan da kansu. zama mara motsi.

Yanzu, motsawa tare da matsayi daga ƙasa zuwa sama, bari mu yi la'akari dalla dalla dalla-dalla abubuwan da aka jera na tsarin watsa bayanai a cikin magudanar ruwa.

Toshe bayanai dblk_t

Toshe bayanan ya ƙunshi kan kai da ma'ajin bayanai. An siffanta taken ta hanyar tsari mai zuwa,

typedef struct datab
{
unsigned char *db_base; // Указатель на начало буфер данных.
unsigned char *db_lim;  // Указатель на конец буфер данных.
void (*db_freefn)(void*); // Функция освобождения памяти при удалении блока.
int db_ref; // Счетчик ссылок.
} dblk_t;

Filayen tsarin sun ƙunshi masu nuni zuwa farkon buffer, ƙarshen buffer, da aikin share bayanan buffer. Ƙarshe a cikin rubutun kai db_ref - ma'aunin tunani, idan ya kai sifili, wannan yana aiki azaman sigina don share wannan toshe daga ƙwaƙwalwar ajiya. Idan an ƙirƙiri toshe bayanan ta aikin datab_alloc() , to za a sanya buffer data cikin ƙwaƙwalwar ajiya nan da nan bayan taken. A duk sauran lokuta, ana iya samun buffer a wani wuri dabam. Maɓallin bayanai zai ƙunshi samfuran sigina ko wasu bayanan da muke son aiwatarwa tare da masu tacewa.

An ƙirƙiri sabon misali na toshe bayanai ta amfani da aikin:

dblk_t *datab_alloc(int size);

A matsayin sigar shigarwa, ana ba da girman bayanan da toshe zai adana. Ana keɓance ƙarin ƙwaƙwalwar ajiya don sanya taken - tsari - a farkon ƙwaƙwalwar da aka keɓe datab. Amma lokacin amfani da wasu ayyuka, wannan ba koyaushe yake faruwa ba; a wasu lokuta, ma'ajin bayanan na iya kasancewa dabam daga maɓallin toshe bayanai. Lokacin ƙirƙirar tsari, ana saita filayen ta yadda filin sa db_base ya nuna farkon yankin bayanan, kuma db_lim zuwa karshensa. Ƙididdigar haɗin kai db_ref an saita zuwa daya. An saita mai nuna aikin share bayanai zuwa sifili.

Sako mblk_t

Kamar yadda aka bayyana, abubuwan jerin gwano iri ne mblk_t, an siffanta shi kamar haka:

typedef struct msgb
{
  struct msgb *b_prev;   // Указатель на предыдущий элемент списка.
  struct msgb *b_next;   // Указатель на следующий элемент списка.
  struct msgb *b_cont;   // Указатель для подклейки к сообщению других сообщений, для создания кортежа сообщений.
  struct datab *b_datap; // Указатель на структуру блока данных.
  unsigned char *b_rptr; // Указатель на начало области данных для чтения данных буфера b_datap.
  unsigned char *b_wptr; // Указатель на начало области данных для записи данных буфера b_datap.
  uint32_t reserved1;    // Зарезервированное поле1, медиастример помещает туда служебную информацию. 
  uint32_t reserved2;    // Зарезервированное поле2, медиастример помещает туда служебную информацию.
  #if defined(ORTP_TIMESTAMP)
  struct timeval timestamp;
  #endif
  ortp_recv_addr_t recv_addr;
} mblk_t;

tsarin mblk_t ya ƙunshi nuni a farkon b_na baya, b_na gaba, waɗanda suke wajibi ne don tsara jerin abubuwan haɗin kai biyu (wanda shine jerin gwano layi_t).

Sai mai nuni ya zo b_ci gaba, wanda ake amfani dashi kawai lokacin da saƙon ya kasance wani ɓangare na tuple. Ga saƙon ƙarshe a cikin tuple, wannan mai nunin ya kasance banza.

Na gaba za mu ga mai nuni zuwa toshe bayanai b_data, wanda sakon ya wanzu. Yana biye da masu nuni zuwa wurin da ke cikin toshe bayanai. Filin b_rptr Yana ƙayyade wurin da za a karanta bayanai daga ma'ajin. Filin b_wpr yana nuna wurin da za a yi rubutu zuwa ga buffer.

Sauran filayen suna da yanayin sabis kuma basu da alaƙa da aikin hanyar canja wurin bayanai.

A ƙasa akwai saƙo guda ɗaya mai suna m1 da kuma bayanan block d1.
Binciko injin Mediastreamer2 VoIP. Kashi na 11
Hoto na gaba yana nuna tarin saƙonni guda uku m1, m1_1, m1_2.
Binciko injin Mediastreamer2 VoIP. Kashi na 11

Ayyukan saƙo mblk_t

Wani sabon sako mblk_t halitta ta hanyar aikin:

mblk_t *allocb(int size, int pri); 

ta sanya sabon saƙo a ƙwaƙwalwar ajiya mblk_t tare da toshe bayanai na ƙayyadaddun girman size, hujja ta biyu - kyauta ba a yi amfani da shi a cikin wannan sigar ɗakin karatu ba. Ya kamata ya kasance sifili. Yayin aikin aikin, za a keɓe ƙwaƙwalwar ajiya don tsarin sabon saƙon kuma za a kira aikin mblk_init(), wanda zai sake saita duk filayen da aka ƙirƙira na tsarin sannan, ta amfani da abin da aka ambata a sama datab_alloc(), zai haifar da buffer bayanai. Bayan haka za a daidaita filayen da ke cikin tsarin:

mp->b_datap=datab;
mp->b_rptr=mp->b_wptr=datab->db_base;
mp->b_next=mp->b_prev=mp->b_cont=NULL;

A wurin fitarwa muna karɓar sabon saƙo tare da filaye da aka fara farawa da buffer bayanai mara komai. Don ƙara bayanai zuwa saƙo, kuna buƙatar kwafe shi zuwa ma'aunin toshe bayanai:

memcpy(msg->b_rptr, data, size);

inda data mai nuni ga tushen bayanai, kuma size - girman su.
sannan kuna buƙatar sabunta mai nuni zuwa wurin rubutu domin ya sake yin nuni zuwa farkon wurin kyauta a cikin buffer:

msg->b_wptr = msg->b_wptr + size

Idan kana buƙatar ƙirƙirar saƙo daga mabuɗin da ke akwai, ba tare da kwafi ba, sannan yi amfani da aikin:

mblk_t *esballoc(uint8_t *buf, int size, int pri, void (*freefn)(void*)); 

Aikin, bayan ƙirƙirar saƙon da tsarin toshe bayanai, zai daidaita masu nuni zuwa bayanan a adireshin. bufi. Wadancan. a wannan yanayin, ma'aunin bayanan ba ya samuwa bayan filayen kan layi na toshe bayanan, kamar yadda ya faru lokacin ƙirƙirar toshe bayanai tare da aikin. datab_alloc(). Buffer tare da bayanan da aka wuce zuwa aikin zai kasance a inda yake, amma tare da taimakon masu nuni za a haɗa shi zuwa sabon rubutun da aka ƙirƙira na toshe bayanai, kuma, daidai da haka, zuwa saƙon.

Zuwa sako daya mblk_t Ana iya haɗa tubalan bayanai da yawa a jere. Ana yin wannan ta aikin:

mblk_t * appendb(mblk_t *mp, const char *data, int size, bool_t pad); 

mp - saƙon da za a ƙara wani shingen bayanai zuwa gare shi;
data - mai nuni ga toshe, kwafin wanda za a ƙara shi zuwa saƙon;
size - girman bayanai;
pad - Tuta cewa girman ƙwaƙwalwar da aka keɓe dole ne a daidaita shi tare da iyaka mai 4-byte (za a yi fakiti tare da sifili).

Idan akwai isasshen sarari a cikin bayanan bayanan saƙon da ke akwai, to za a liƙa sabon bayanan a bayan bayanan da ke can. Idan akwai ƙarancin sarari kyauta a cikin buffer data saƙo fiye da size, sa'an nan kuma an ƙirƙiri sabon saƙo tare da isassun girman buffer kuma ana kwafi bayanan zuwa buffer ɗin sa. Wannan sabon saƙo ne, mai alaƙa da na asali ta amfani da mai nuni b_ci gaba. A wannan yanayin, saƙon yana juya zuwa tuple.

Idan kuna buƙatar ƙara wani toshe na bayanai zuwa tuple, to kuna buƙatar amfani da aikin:

void msgappend(mblk_t *mp, const char *data, int size, bool_t pad);

za ta sami saƙo na ƙarshe a cikin tuple (yana da b_ci gaba zai zama banza) kuma zai kira aikin don wannan saƙon appendb().

Kuna iya gano girman bayanai a cikin saƙo ko tuple ta amfani da aikin:

int msgdsize(const mblk_t *mp);

zai madauki cikin duk saƙonnin da ke cikin tuple kuma ya dawo da jimlar adadin bayanai a cikin ma'ajin bayanan waɗancan saƙonnin. Ga kowane saƙo, ana ƙididdige adadin bayanai kamar haka:

 mp->b_wptr - mp->b_rptr

Don haɗa tuples guda biyu, yi amfani da aikin:

mblk_t *concatb(mblk_t *mp, mblk_t *newm);

ta dora tuple sabo zuwa wutsiya na tuple mp kuma ya mayar da mai nuni zuwa saƙon ƙarshe na sakamakon tuple.

Idan ya cancanta, ana iya juya tuple zuwa saƙo ɗaya tare da toshe ɗaya na bayanai; ana yin haka ta hanyar aikin:

void msgpullup(mblk_t *mp,int len);

idan gardama len shine -1, sa'an nan kuma an ƙayyade girman ma'ajin da aka keɓe ta atomatik. Idan len lamba ce tabbatacce, za a ƙirƙiri buffer na wannan girman kuma za a kwafi bayanan saƙon tuple a ciki. Idan buffer ya ƙare, kwafi zai tsaya a nan. Saƙon farko na tuple zai karɓi sabon babban buffer tare da kwafi bayanai. Za a share ragowar saƙonnin kuma za a mayar da ƙwaƙwalwar ajiya cikin tudu.

Lokacin share tsari mblk_t Ana la'akari da ƙididdige ƙididdiga na toshe bayanai idan, lokacin kira freeb() sai ya zama sifili, sannan ana share ma'aunin bayanan tare da misalin mblk_t, wanda ke nuni da shi.

Fara filayen sabon saƙo:

void mblk_init(mblk_t *mp);

Ƙara wani yanki na bayanai zuwa saƙon:

mblk_t * appendb(mblk_t *mp, const char *data, size_t size, bool_t pad);

Idan sabon bayanan bai dace da sarari kyauta na buffer ɗin saƙon ba, to, an haɗa saƙon da aka ƙirƙira daban tare da buffer na girman girman da ake buƙata akan saƙon (an saita mai nuni ga ƙarin saƙon a cikin saƙon farko) kuma saƙo ya juya ya zama tuple.

Ƙara wani yanki na bayanai zuwa tuple:

void msgappend(mblk_t *mp, const char *data, size_t size, bool_t pad); 

Aikin yana kiran appendb() a madauki.

Haɗa tuples biyu zuwa ɗaya:

mblk_t *concatb(mblk_t *mp, mblk_t *newm);

Sako sabo za a makala zuwa mp.

Yin kwafin saƙo ɗaya:

mblk_t *copyb(const mblk_t *mp);

Cikakken kwafin tuple tare da duk tubalan bayanai:

mblk_t *copymsg(const mblk_t *mp);

Abubuwan da ke cikin tuple suna kwafi ta aikin kwafi().

Ƙirƙirar kwafin saƙo mai sauƙi mblk_t. A wannan yanayin, bayanan toshe ba a kwafi ba, amma ana ƙara ƙima db_ref:

mblk_t *dupb(mblk_t *mp);

Yin kwafin tuple mai sauƙi. Ba a kwafi bayanan tubalan ba, ana ƙara ƙididdigansu kawai db_ref:

mblk_t *dupmsg(mblk_t* m);

Manne duk saƙonnin tuple cikin saƙo ɗaya:

void msgpullup(mblk_t *mp,size_t len);

Idan hujja len shine -1, sa'an nan kuma an ƙayyade girman ma'ajin da aka keɓe ta atomatik.

Share sako, tuple:

void freemsg(mblk_t *mp);

An rage ƙididdige ƙididdigar toshewar bayanan da ɗaya. Idan ya kai sifili, toshewar bayanai shima yana gogewa.

Lissafin jimillar adadin bayanai a cikin saƙo ko tuple.

size_t msgdsize(const mblk_t *mp);

Maido da sako daga wutsiyar layin:

mblk_t *ms_queue_peek_last (q);

Kwafi abubuwan da ke cikin filayen da aka keɓance na saƙo ɗaya zuwa wani saƙo (a zahiri, waɗannan filayen suna ɗauke da tutoci waɗanda masu rafi na watsa labarai ke amfani da su):

mblk_meta_copy(const mblk_t *source, mblk *dest);

Layi layi_t

Ana aiwatar da jerin gwanon saƙo a cikin mai watsa shirye-shiryen watsa labarai azaman jerin madauwari biyu masu alaƙa. Kowane ɓangaren jeri ya ƙunshi mai nuni zuwa toshe bayanai tare da samfuran sigina. Ya zama cewa kawai masu nuni ga toshe bayanai suna motsawa bi da bi, yayin da bayanan da kansu ke zama mara motsi. Wadancan. kawai hanyoyin haɗi zuwa gare su ana motsa su.
Tsarin da ke kwatanta jerin gwano layi_t, wanda aka nuna a kasa:

typedef struct _queue
{
   mblk_t _q_stopper; /* "Холостой" элемент очереди, не указывает на данные, используется только для управления очередью. При инициализации очереди (qinit()) его указатели настраиваются так, чтобы они указывали на него самого. */
   int q_mcount;        // Количество элементов в очереди.
} queue_t;

Tsarin ya ƙunshi filin - mai nuni _q_mai tsayawa rubuta *mblk_t, yana nuna kashi na farko (saƙo) a cikin jerin gwano. Filin na biyu na tsarin shine ma'aunin saƙo a cikin jerin gwano.
Hoton da ke ƙasa yana nuna jerin gwano mai suna q1 mai ɗauke da saƙonni 4 m1, m2, m3, m4.
Binciko injin Mediastreamer2 VoIP. Kashi na 11
Hoto mai zuwa yana nuna jerin gwano mai suna q1 mai ɗauke da saƙonni 4 m1,m2,m3,m4. Message m2 shine shugaban tuple wanda ya ƙunshi ƙarin saƙonni biyu m2_1 da m2_2.

Binciko injin Mediastreamer2 VoIP. Kashi na 11

Ayyuka don aiki tare da layin layi queue_t

Farawa jerin gwano:

void qinit(queue_t *q);

filin _q_mai tsayawa (nan gaba za mu kira shi "Stopper") an fara shi ta hanyar aikin mblk_init(), an daidaita sinadarinsa na baya da mai nuni na gaba don nunawa kansa. An sake saita ma'aunin kashi na layi zuwa sifili.

Ƙara sabon abu (saƙonni):

void putq(queue_t *q, mblk_t *m);

Sabon kashi m an ƙara zuwa ƙarshen jeri, ana daidaita maƙallan element ɗin ta yadda mai tsayawa ya zama na gaba a gare shi, kuma ya zama abin da ya gabata na mai tsayawa. An ƙara ƙididdigan abubuwan layi.

Maido da wani abu daga jerin gwano:

mblk_t * getq(queue_t *q); 

An dawo da saƙon da ke zuwa bayan madaidaicin, kuma ana rage ma'aunin abubuwan. Idan babu abubuwa a cikin jerin gwano sai mai tsayawa, to 0 yana dawowa.

Saka sako a cikin layi:

void insq(queue_t *q, mblk_t *emp, mblk_t *mp); 

Abu mp shigar kafin kashi emp. Idan emp=0, sa'an nan an ƙara saƙon zuwa wutsiya na jerin gwano.

Maido da sako daga shugaban jerin gwano:

void remq(queue_t *q, mblk_t *mp); 

An rage ma'aunin kashi.

Karatun mai nuni ga kashi na farko a cikin jerin gwano:

mblk_t * peekq(queue_t *q); 

Cire duk abubuwa daga jerin gwano yayin share abubuwan da kansu:

void flushq(queue_t *q, int how);

shaida yaya ba a amfani. An saita counter element counter zuwa sifili.

Macro don karanta mai nuni zuwa kashi na ƙarshe na jerin gwano:

mblk_t * qlast(queue_t *q);

Lokacin aiki tare da layin saƙo, lura cewa lokacin da kake kira ms_queue_put(q, m) tare da ma'anar banza zuwa saƙon, madaukai na aiki. Shirin ku zai daskare. yana yin haka ms_queue_na gaba (q, m).

Haɗa matattara

Ana amfani da layin da aka bayyana a sama don isar da saƙon daga wannan tacewa zuwa wani ko kuma daga ɗaya zuwa filtata da yawa. Filters da haɗin haɗin su suna samar da jadawali. Shigar ko fitarwa na tacewa za a kira kalmar gaba ɗaya “pin”. Don bayyana tsarin da ake haɗa masu tacewa da juna, mai watsa shirye-shiryen watsa labaru yana amfani da manufar "siginar sigina". Ma'anar sigina shine tsari _MSCP, wanda ke ƙunshe da mai nuni ga tacewa da adadin ɗaya daga cikin fil ɗinsa; don haka, yana bayyana haɗin ɗaya daga cikin abubuwan shigarwa ko abubuwan da ke cikin tacewa.

Wurin sigina na jadawali sarrafa bayanai

typedef struct _MSCPoint{
struct _MSFilter *filter; // Указатель на фильтр медиастримера.
int pin;                        // Номер одного из входов или выходов фильтра, т.е. пин.
} MSCPoint;

An ƙididdige fil ɗin fil daga sifili.

Haɗin fil biyu ta hanyar layin saƙo yana bayyana ta tsarin _MSQueue, wanda ya ƙunshi layin saƙo da masu nuni zuwa ga sigina guda biyu da yake haɗawa:

typedef struct _MSQueue
{
queue_t q;
MSCPoint prev;
MSCPoint next;
}MSQueue;

Za mu kira wannan tsarin hanyar haɗin sigina. Kowane tace mai rafi mai watsa labarai yana ƙunshe da tebur na hanyoyin shigar da bayanai da tebur na hanyoyin haɗin kai (MSQueue). Ana saita girman teburi lokacin ƙirƙirar tacewa; mun riga mun yi wannan ta amfani da nau'in nau'in canjin da aka fitar MSFilterDesc, lokacin da muka inganta namu tace. A ƙasa akwai wani tsari wanda ke bayyana kowane tacewa a cikin magudanar ruwa, MSFilter:


struct _MSFilter{
    MSFilterDesc *desc;    /* Указатель на дескриптор фильтра. */
    /* Защищенные атрибуты, их нельзя сдвигать или убирать иначе будет нарушена работа с плагинами. */
    ms_mutex_t lock;      /* Семафор. */
    MSQueue **inputs;     /* Таблица входных линков. */
    MSQueue **outputs;    /* Таблица выходных линков. */
    struct _MSFactory *factory; /* Указатель на фабрику, которая создала данный экземпляр фильтра. */
    void *padding;              /* Не используется, будет задействован если добавятся защищенные поля. */
    void *data;                 /* Указатель на произвольную структуру для хранения данных внутреннего состояния фильтра и промежуточных вычислений. */
    struct _MSTicker *ticker;   /* Указатель на объект тикера, который не должен быть нулевым когда вызывается функция process(). */
    /*private attributes, they can be moved and changed at any time*/
    MSList *notify_callbacks; /* Список обратных вызовов, используемых для обработки событий фильтра. */
    uint32_t last_tick;       /* Номер последнего такта, когда выполнялся вызов process(). */ 
    MSFilterStats *stats;     /* Статистика работы фильтра.*/
    int postponed_task; /*Количество отложенных задач. Некоторые фильтры могут откладывать обработку данных (вызов process()) на несколько тактов.*/
    bool_t seen;  /* Флаг, который использует тикер, чтобы помечать что этот экземпляр фильтра он уже обслужил на данном такте.*/
};
typedef struct _MSFilter MSFilter;

Bayan mun haɗa masu tacewa a cikin shirin C daidai da tsarin mu (amma ba mu haɗa alamar ba), ta haka ne muka ƙirƙiri jadawali da aka ba da umarni, nodes ɗin su ne misalin tsarin. MSFilter, kuma gefuna misalai ne na haɗin gwiwa MSQueue.

Bayan fage ayyukan ticker

Lokacin da na gaya muku cewa ticker shine tace tushen ticks, ba duka ba ne game da shi. Ticker abu ne da ke gudanar da ayyuka akan agogo tsari() duk tacewa na kewaye (graph) wanda aka haɗa shi. Lokacin da muka haɗa ticker zuwa fil fil a cikin shirin C, za mu nuna alamar jadawali wanda zai sarrafa daga yanzu har sai mun kashe shi. Bayan haɗawa, ticker ya fara bincika jadawali da aka damƙa masa kulawa, yana tattara jerin abubuwan tacewa waɗanda suka haɗa da shi. Don kar a “ƙidaya” tacewa iri ɗaya sau biyu, yana yiwa matatun da aka gano ta sanya akwati a ciki. gani. Ana gudanar da binciken ne ta hanyar amfani da allunan haɗin da kowane tacewa ke da shi.

Yayin ziyarar gabatarwa na jadawali, mai tikiti yana duba ko a cikin masu tacewa akwai aƙalla wanda ke aiki azaman tushen toshe bayanai. Idan babu ko ɗaya, to ana ɗaukar jadawali ba daidai ba kuma alamar ta fashe.

Idan jadawali ya zama “daidai”, ga kowane tacewa da aka samu, ana kiran aikin don farawa tsari (). Da zaran lokacin ya zo don sake zagayowar sarrafawa na gaba (kowane miliyon 10 ta tsohuwa), alamar ta kira aikin. tsari() ga duk abubuwan da aka samo asali a baya, sannan ga sauran matatun da ke cikin jerin. Idan tace tana da hanyoyin shigar da bayanai, to tana gudanar da aikin tsari() yana maimaituwa har sai layukan hanyar shigar sun zama fanko. Bayan wannan, yana matsawa zuwa tacewa na gaba a cikin jerin kuma “gungurawa” har sai hanyoyin shigar da bayanai ba su da saƙo. Alamar tana motsawa daga tacewa don tacewa har sai lissafin ya ƙare. Wannan yana kammala sarrafa zagayowar.

Yanzu za mu koma tuples kuma muyi magana game da dalilin da yasa aka ƙara irin wannan mahaɗin zuwa mai rafi mai rahusa. Gabaɗaya, adadin bayanan da algorithm ke aiki a cikin tacewa bai zo daidai ba kuma ba adadi mai yawa na girman ma'ajin bayanan da aka karɓa a wurin shigarwa ba. Misali, muna rubuta matatar da ke aiwatar da saurin canji na Fourier, wanda ta ma'anarsa kawai zai iya aiwatar da tubalan bayanai waɗanda girmansu ke da ƙarfi biyu. Bari ya zama kirga 512. Idan tashar tarho ne ya samar da bayanan, to, ma'aunin bayanan kowane saƙo a wurin shigarwa zai kawo mana samfuran sigina 160. Yana da jaraba kada a tattara bayanai daga shigarwar har sai adadin bayanan da ake buƙata yana nan. Amma a wannan yanayin, karo zai faru tare da ticker, wanda ba zai yi nasara ba don ƙoƙarin gungurawa tacewa har sai hanyar shigarwa ta zama fanko. A baya, mun sanya wannan doka a matsayin ka'ida ta uku na tacewa. Bisa ga wannan ƙa'idar, aikin aikin tace() dole ne ya ɗauki duk bayanai daga layin shigarwa.

Bugu da ƙari, ba zai yiwu a ɗauki samfurori 512 kawai daga shigarwar ba, tun da za ku iya ɗaukar duka tubalan kawai, watau. Tacewar za ta ɗauki samfurori 640 kuma ta yi amfani da 512 daga cikinsu, ragowar kafin tara sabon ɓangaren bayanai. Don haka, tacewar mu, ban da babban aikinsa, dole ne ta samar da ayyuka na taimako don matsakaicin ajiyar bayanan shigarwa. Masu haɓaka kafofin watsa labaru da mafita ga wannan matsala ta gaba ɗaya sun haɓaka wani abu na musamman - MSBufferizer (bufferer), wanda ke magance wannan matsalar ta amfani da tuples.

Bufferizer (MSBufferizer)

Wannan wani abu ne da zai tara bayanan shigar da bayanai a cikin tace sannan ya fara mika shi don sarrafa shi da zarar adadin bayanan ya isa don tafiyar da algorithm filter. Yayin da buffer ke tara bayanai, tacewa za ta yi aiki a yanayin zaman banza, ba tare da yin amfani da ƙarfin sarrafa na'urar ba. Amma da zaran aikin karantawa daga mai buffer ya dawo da darajar wanin sifili, aikin () aikin tacewa zai fara ɗauka da sarrafa bayanai daga bufferer a cikin sassan girman da ake buƙata, har sai ya ƙare.
Bayanan da har yanzu ba a buƙata ba ya kasance a cikin ma'ajin a matsayin kashi na farko na tuple, wanda aka haɗa tubalan bayanan shigarwa na gaba.

Tsarin da ke bayyana buffer:

struct _MSBufferizer{
queue_t q; /* Очередь сообщений. */
int size; /* Суммарный размер данных находящихся в буферизаторе в данный момент. */
};
typedef struct _MSBufferizer MSBufferizer;

Ayyuka don aiki tare da MSBufferizer

Ƙirƙirar sabon misalin buffer:

MSBufferizer * ms_bufferizer_new(void);

An keɓance ƙwaƙwalwar ajiya, an fara a ciki ms_bufferizer_init() kuma an mayar da mai nuni.

Ayyukan farawa:

void ms_bufferizer_init(MSBufferizer *obj); 

Ana fara jerin gwano q, filin size an saita zuwa sifili.

Ƙara sako:

void ms_bufferizer_put(MSBufferizer *obj, mblk_t *m); 

Ana ƙara saƙo m zuwa jerin gwano. Ana ƙara girman adadin bayanan tubalan zuwa size.

Canja wurin duk saƙonni daga layin bayanan hanyar haɗin yanar gizo zuwa majigi q:

void ms_bufferizer_put_from_queue(MSBufferizer *obj, MSQueue *q);   

Canja wurin saƙonni daga hanyar haɗi q a cikin buffer ana yin amfani da aikin ms_bufferizer_put().

Karatu daga rumbun adana bayanai:

int ms_bufferizer_read(MSBufferizer *obj, uint8_t *data, int datalen); 

Idan girman bayanan da aka tara a cikin buffer bai kai wanda aka nema ba (datalen), sannan aikin ya dawo sifili, ba a kwafin bayanai zuwa bayanai. In ba haka ba, ana yin kwafin bayanai na jeri daga tuples da ke cikin buffer. Bayan kwafi, ana share tuple kuma an 'yantar da ƙwaƙwalwar ajiya. Kwafi yana ƙare a lokacin da aka kwafi datalen bytes. Idan sarari ya ƙare a tsakiyar bayanan toshe, to a cikin wannan sakon, toshe bayanan za a rage zuwa sauran ɓangaren da ba a kwafi ba. Lokaci na gaba da kuka kira, za a ci gaba da yin kwafi daga wannan batu.

Karanta adadin bayanan da ake samu a halin yanzu a cikin buffer:

int ms_bufferizer_get_avail(MSBufferizer *obj); 

Yana dawo da filin size bufferer.

Yin watsi da ɓangaren bayanan a cikin ma'ajin:

void ms_bufferizer_skip_bytes(MSBufferizer *obj, int bytes);

Ana dawo da ƙayyadadden adadin bytes na bayanai kuma ana zubar dasu. Ana zubar da mafi tsufa bayanai.

Share duk saƙonnin da ke cikin buffer:

void ms_bufferizer_flush(MSBufferizer *obj); 

An sake saita ma'aunin bayanan zuwa sifili.

Share duk saƙonnin da ke cikin buffer:

void ms_bufferizer_uninit(MSBufferizer *obj); 

Ba a sake saita ma'auni ba.

Cire buffer da 'yantar da ƙwaƙwalwar ajiya:

void ms_bufferizer_destroy(MSBufferizer *obj);  

Ana iya samun misalan yin amfani da bufferer a cikin lambar tushe na matatun mai rafi da yawa. Misali, a cikin matatar MS_L16_ENC, wanda ke sake tsara bytes a cikin samfuran daga tsarin hanyar sadarwa zuwa odar mai masauki: l16.c

A cikin kasida ta gaba, za mu dubi batun kimanta nauyi akan ticker da kuma hanyoyin da za a magance wuce kima lodin kwamfuta a cikin magudanar ruwa.

source: www.habr.com

Add a comment