Sunday, September 2, 2018

回線交換フォールバック CSFB - モバイルアイドルモードでの着信コール




1.G MSCはIAMを受信します。
2. SRI(Send Routing Info)手順については、TS 23.018 3GPPを参照してください。
3.G MSCは着信側のMSCにIAMを送信する。

4.MMEは、SGsインタフェースを介してMSCからのMT側IMSIメッセージを有するページング要求を受信する。 IMSIは、無線インタフェース上のページングアドレスとして使用されるS TMSIを見つけるためにMMEによって使用される。位置情報がMMEによって確実に知られている場合(すなわち、MMEがTAのリストを記憶する)、MMEはUEをすべてのTAでページングする。 MMEがUEのために格納されたTAリストを有していない場合、MMEは、UEをページングするためにMSCから受信した位置情報を使用すべきである。
この手順は、ステップ3の前に、HSSからMAP_PRNを受信した直後に、プレページングが導入されている場合に行われます。
MMEが、EPSサービスのためのデタッチと見なされるUEのページング要求メッセージを受信した場合、MMEは、ページング拒否メッセージを適切な原因値と共にMSCに送信する。この拒否は、MSCがAまたはIu-csインタフェースを介してUEをページングするようにトリガする。
NMO IIまたはIIIにおけるCSフォールバック可能UEの場合、例えば、VLRがSGアソシエーションを維持している間に、UEアイドルモード移動性のためにMMEがSGアソシエーションを解放する場合がある。

5.MMEが、AttachまたはCombined TA / LA Update手順の間にMMEがUEに「SMS-only」指示を返さなかった場合、MMEは、各eNodeBにページングメッセージを送信する。 ページングメッセージは、適切なUEアイデンティティ(すなわち、S TMSIまたはIMSI)およびどのドメイン(CSまたはPS)がページングメッセージを開始したかを示すCNドメインインジケータを含む。 この場合、MMEによって「CS」に設定されなければならない。
アタッチまたは結合TA / LA更新手順中にMMEがUEに「SMS専用」指示を返した場合、MMEはeノードBにページングを送信してはならず、MSCに向けてページング拒否を送信してCSページング手順を停止し、このCSFB手順は停止する 。

6. ページング手順の無線リソース部分が発生する。 このメッセージは、適切なUEアイデンティティ(すなわち、S TMSIまたはIMSI)およびCNドメインインジケータを含む。

7a。 UEは、RRC接続を確立し、MMEに拡張サービス要求(CSフォールバックインジケータ)を送信する。 UEは、そのS-TMSIをRRCシグナリングに示す。拡張サービス要求メッセージは、RRCおよびS1APメッセージにカプセル化される。 CSフォールバックインジケータは、このUEのCSフォールバックが必要であることをMMEに示す。 MMEは、UEがアイドルモードにあった(したがって、例えばUEが呼出回線識別情報を受信して​​いない)という指示を含むSGSサービス要求メッセージをMSCに送信する。 SGsサービス要求メッセージの受信は、SGsインタフェースページングメッセージを再送信するMSCを停止する。
発呼者が潜在的に長い間無音状態に陥るのを避けるために、MSCは、呼が進行中であることを発呼者に知らせるために、アイドルモード指示を含むSGSサービス要求メッセージをトリガとして使用することができる。
7b.MMEは、UEをUTRAN / GERANに移動させるためにeNodeBを指示するためにS1AP:Initial UE Con​​text Setupを送信する。 CSドメインの登録されたPLMNは、MMEによって割り当てられたLAIに含まれるPLMN IDによって識別される。
7c。 (上記では見えない)eNodeBは、S1-AP:Initial UE Con​​text Setup Responseメッセージで応答する。

さらに、上記の手順を完了した後は、アクティブモードで回線交換フォールバックCSFB - 移動体着信呼で以前に説明したアクティブモードと同じですが、PS HOはありません。
以下に示す手順のステップ2から開始します。 これは、上記のリンクをたどって見つけたものの修正されたバージョン(ステップ1がなくなった)です。

Cの多次元配列

C言語は多次元配列を可能にします。 ここに多次元配列宣言の一般的な形式があります
type name[size1][size2]...[sizeN];

たとえば、次の宣言は3次元の整数配列を作成します
int threedim[5][10][4];


2次元配列
多次元配列の最も単純な形式は2次元配列です。 2次元配列は、本質的に、1次元配列のリストである。 サイズ[x] [y]の2次元整数配列を宣言するには、次のように記述します
type arrayName [ x ][ y ];

typeは任意の有効なCデータ型であり、arrayNameは有効なC識別子です。 2次元配列は、x個の行とy個の列を持つテーブルと考えることができます。 3つの行と4つの列を含む2次元配列aは、以下のように示すことができる
Two Dimensional Arrays in C

したがって、配列aのすべての要素は、a [i] [j]という形式の要素名で識別されます。ここで 'a'は配列の名前で、 'i'と 'j'は一意に識別する添え字です 'a'の各要素。


2次元配列の初期化
多次元配列は、各行に括弧で囲まれた値を指定することによって初期化することができます。 以下は3行の配列で、各行は4列です。
int a[3][4] = {  
   {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
   {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
   {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
};
目的の行を示すネストされた中カッコはオプションです。 次の初期化は前の例と同じです

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};


2次元配列要素へのアクセス
2次元配列内の要素は、添え字、すなわち配列の行インデックスおよび列インデックスを使用してアクセスされる。 例えば
int val = a[2][3];

上記のステートメントは、配列の3番目の行から4番目の要素を取得します。 上記の図で確認できます。 ネストされたループを使用して2次元配列を処理した次のプログラムを確認しましょう
#include <stdio.h>
 
int main () {

   /* an array with 5 rows and 2 columns*/
   int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};
   int i, j;
 
   /* output each array element's value */
   for ( i = 0; i < 5; i++ ) {

      for ( j = 0; j < 2; j++ ) {
         printf("a[%d][%d] = %d\n", i,j, a[i][j] );
      }
   }
   
   return 0;
}

a[0][0]: 0
a[0][1]: 0
a[1][0]: 1
a[1][1]: 2
a[2][0]: 2
a[2][1]: 4
a[3][0]: 3
a[3][1]: 6
a[4][0]: 4
a[4][1]: 8

上で説明したように、任意の次元数の配列を持つことができますが、作成する配列の大半は1次元または2次元です。






Cでの関数引数としての配列の受け渡し

関数内で引数として一次元配列を渡したい場合は、以下の3つの方法のいずれかで仮引数を宣言し、3つの宣言方法すべてが同様の結果を生成する必要があります。 受け取る。 同様に、多次元配列を仮パラメータとして渡すことができます。

ウェイ1
ポインタとしての正式なパラメータ
void myFunction(int *param) {
   .
   .
   .
}

ウェイ-2
サイズの配列としての正式なパラメータ
void myFunction(int param[10]) {
   .
   .
   .
}

道 - 3
サイズの指定されていない配列としての正式なパラメータ
void myFunction(int param[]) {
   .
   .
   .
}



今度は、次の関数を考えてみましょう。これは、配列を別の引数と共に引数としてとり、渡された引数に基づいて、次のように配列を渡される数値の平均を返します
double getAverage(int arr[], int size) {

   int i;
   double avg;
   double sum = 0;

   for (i = 0; i < size; ++i) {
      sum += arr[i];
   }

   avg = sum / size;

   return avg;
}
さて、上記の関数を以下のように呼ぶ

#include <stdio.h>
 
/* function declaration */
double getAverage(int arr[], int size);

int main () {

   /* an int array with 5 elements */
   int balance[5] = {1000, 2, 3, 17, 50};
   double avg;

   /* pass pointer to the array as an argument */
   avg = getAverage( balance, 5 ) ;
 
   /* output the returned value */
   printf( "Average value is: %f ", avg );
    
   return 0;
}
Average value is: 214.400000

ご覧のように、配列の長さは、Cが仮パラメータの境界チェックを実行しないため、関数が関係する限り重要ではありません。



Cでの配列へのポインタ

この章は、「ポインタ」の章で説明するまで理解していない可能性が高いです。

Cでポインターを理解していると仮定してみましょう。配列名は配列の最初の要素への定数ポインタです。 したがって、宣言では
double balance[50];

balanceは&balance [0]へのポインタであり、これは配列のバランスの最初の要素のアドレスです。 したがって、以下のプログラムフラグメントは、pをbalanceの最初の要素のアドレスとして割り当てます
double *p;
double balance[10];

p = balance;

配列名を定数ポインタとして使用することは正当であり、その逆もあります。 したがって、*(残高+ 4)は残高[4]でデータにアクセスする正当な方法です。

最初の要素のアドレスを 'p'に格納すると、* p、*(p + 1)、*(p + 2)などを使用して配列要素にアクセスできます。 以下に、上で論じたすべての概念を示す例を示します

#include <stdio.h>

int main () {

   /* an array with 5 elements */
   double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
   double *p;
   int i;

   p = balance;
 
   /* output each array element's value */
   printf( "Array values using pointer\n");
 
   for ( i = 0; i < 5; i++ ) {
      printf("*(p + %d) : %f\n",  i, *(p + i) );
   }

   printf( "Array values using balance as address\n");
 
   for ( i = 0; i < 5; i++ ) {
      printf("*(balance + %d) : %f\n",  i, *(balance + i) );
   }
 
   return 0;
}
Array values using pointer
*(p + 0) : 1000.000000
*(p + 1) : 2.000000
*(p + 2) : 3.400000
*(p + 3) : 17.000000
*(p + 4) : 50.000000
Array values using balance as address
*(balance + 0) : 1000.000000
*(balance + 1) : 2.000000
*(balance + 2) : 3.400000
*(balance + 3) : 17.000000
*(balance + 4) : 50.000000

上記の例では、pはdoubleへのポインタです。つまり、double型の変数のアドレスを格納できます。 上記の例で示したように、pにアドレスがあると、* pはpに格納されているアドレスで利用可能な値を返します。


C の関数からポインタを返す

最後の章では、Cプログラミングがどのようにして関数から配列を返すことができるかを見てきました。 同様に、Cは関数からポインタを返すこともできます。 これを行うには、次の例のようにポインタを返す関数を宣言する必要があります
int * myFunction() {
   .
   .
   .
}
第2のポイントは、関数の外部にあるローカル変数のアドレスを返すのは良い考えではないので、ローカル変数を静的変数として定義する必要があるということです。

ここで、10個の乱数を生成し、ポインタを表す配列名、つまり最初の配列要素のアドレスを使用してそれらを返す次の関数を考えてみましょう。
#include <stdio.h>
#include <time.h>
 
/* function to generate and return random numbers. */
int * getRandom( ) {

   static int  r[10];
   int i;
 
   /* set the seed */
   srand( (unsigned)time( NULL ) );
 
   for ( i = 0; i < 10; ++i) {
      r[i] = rand();
      printf("%d\n", r[i] );
   }
 
   return r;
}
 
/* main function to call above defined function */
int main () {

   /* a pointer to an int */
   int *p;
   int i;

   p = getRandom();
 
   for ( i = 0; i < 10; i++ ) {
      printf("*(p + [%d]) : %d\n", i, *(p + i) );
   }
 
   return 0;
}


1523198053
1187214107
1108300978
430494959
1421301276
930971084
123250484
106932140
1604461820
149169022
*(p + [0]) : 1523198053
*(p + [1]) : 1187214107
*(p + [2]) : 1108300978
*(p + [3]) : 430494959
*(p + [4]) : 1421301276
*(p + [5]) : 930971084
*(p + [6]) : 123250484
*(p + [7]) : 106932140
*(p + [8]) : 1604461820
*(p + [9]) : 149169022










C - ポインタへのポインタ

ポインタへのポインタは、複数の間接的な形式、または一連のポインタです。 通常、ポインタには変数のアドレスが含まれます。 ポインタへのポインタを定義すると、最初のポインタには、次のように実際の値が格納されている位置を指す2番目のポインタのアドレスが格納されます。
Pointer to Pointer in C

ポインタへのポインタである変数は、そのように宣言されなければなりません。 これは、名前の前に追加のアスタリスクを置くことによって行われます。 例えば、次の宣言はint型のポインタへのポインタを宣言します
int **var;

ターゲット値がポインタへのポインタによって間接的に指されている場合、その値にアクセスするには、アスタリスク演算子を2回適用する必要があります(下の例を参照)。
#include <stdio.h>
 
int main () {

   int  var;
   int  *ptr;
   int  **pptr;

   var = 3000;

   /* take the address of var */
   ptr = &var;

   /* take the address of ptr using address of operator & */
   pptr = &ptr;

   /* take the value using pptr */
   printf("Value of var = %d\n", var );
   printf("Value available at *ptr = %d\n", *ptr );
   printf("Value available at **pptr = %d\n", **pptr);

   return 0;
}
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109


配列の詳細
配列はCにとって重要であり、もっと注意が必要です。 配列に関する以下の重要な概念は、Cプログラマには明らかであるべきです

Sr.No.Concept & Description
1Multi-dimensional arrays
C supports multidimensional arrays. The simplest form of the multidimensional array is the two-dimensional array.
2Passing arrays to functions
You can pass to the function a pointer to an array by specifying the array's name without an index.
3Return array from a function
C allows a function to return an array.
4Pointer to an array
You can generate a pointer to the first element of an array by simply specifying the array name, without any index.




Saturday, September 1, 2018

C - ポインタ演算

cの中のポインタは数値であるアドレスです。 したがって、数値の場合と同じように、ポインタに対して算術演算を実行できます。 ポインタに使用できる算術演算子は、++、 - 、+、 - の4つです。

ポインタの算術を理解するために、ptrがアドレス1000を指す整数ポインタであると考えてみましょう.32ビットの整数を仮定すると、ポインタに対して以下の算術演算を実行します
ptr++

上記の操作の後、ptrが増分されるたびに、ptrは位置1004を指します。これは、現在の位置の次の4バイトである次の整数位置を指します。 この操作では、メモリ位置の実際の値に影響を与えることなく、ポインタを次のメモリ位置に移動します。 ptrがアドレスが1000の文字を指している場合、上記の操作は1001で次の文字が使用可能になるため、1001の位置を指します。


ポインタをインクリメントする
定数ポインタであるためインクリメントできない配列名とは異なり、変数ポインタはインクリメントすることができるので、配列の代わりにプログラム内のポインタを使用することをお勧めします。 次のプログラムは、変数ポインタをインクリメントして、配列の各後続要素にアクセスします

#include <stdio.h>

const int MAX = 3;

int main () {

   int  var[] = {10, 100, 200};
   int  i, *ptr;

   /* let us have array address in pointer */
   ptr = var;
 
   for ( i = 0; i < MAX; i++) {

      printf("Address of var[%d] = %x\n", i, ptr );
      printf("Value of var[%d] = %d\n", i, *ptr );

      /* move to the next location */
      ptr++;
   }
 
   return 0;
}
Address of var[0] = bf882b30
Value of var[0] = 10
Address of var[1] = bf882b34
Value of var[1] = 100
Address of var[2] = bf882b38
Value of var[2] = 200


ポインタを減らす
ポインタを減分する場合も同じ考慮事項が適用されます。ポインタは、そのデータ型のバイト数を下に示すように減らします
#include <stdio.h>

const int MAX = 3;

int main () {

   int  var[] = {10, 100, 200};
   int  i, *ptr;

   /* let us have array address in pointer */
   ptr = &var[MAX-1];
 
   for ( i = MAX; i > 0; i--) {

      printf("Address of var[%d] = %x\n", i-1, ptr );
      printf("Value of var[%d] = %d\n", i-1, *ptr );

      /* move to the previous location */
      ptr--;
   }
 
   return 0;
}
Address of var[2] = bfedbcd8
Value of var[2] = 200
Address of var[1] = bfedbcd4
Value of var[1] = 100
Address of var[0] = bfedbcd0
Value of var[0] = 10


ポインタの比較
ポインタは、==、<、>などの関係演算子を使用して比較できます。 p1とp2が、同じ配列の要素など、互いに関連する変数を指している場合、p1とp2を有意義に比較することができます。

以下のプログラムは、前の例を変更します。変数ポインタを指すアドレスが配列の最後の要素のアドレス以下である限り、変数ポインタをインクリメントします。これは&var [MAX-1]

#include <stdio.h>

const int MAX = 3;

int main () {

   int  var[] = {10, 100, 200};
   int  i, *ptr;

   /* let us have address of the first element in pointer */
   ptr = var;
   i = 0;
 
   while ( ptr <= &var[MAX - 1] ) {

      printf("Address of var[%d] = %x\n", i, ptr );
      printf("Value of var[%d] = %d\n", i, *ptr );

      /* point to the previous location */
      ptr++;
      i++;
   }
 
   return 0;
}
Address of var[0] = bfdbcb20
Value of var[0] = 10
Address of var[1] = bfdbcb24
Value of var[1] = 100
Address of var[2] = bfdbcb28
Value of var[2] = 200






Interfaces and their protocol stacks

インタフェースとそのプロトコルスタック 主要なネットワーク要素に精通した後、これら要素間のインタフェースをよりよく知る時期が来ています。 インタフェースは、MME、SGWおよびPGWが他のネットワーク要素(例えば、HSSまたはPCRF)と協働することを可能にする。 それらの...