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 Context Setupを送信する。 CSドメインの登録されたPLMNは、MMEによって割り当てられたLAIに含まれるPLMN IDによって識別される。
7c。 (上記では見えない)eNodeBは、S1-AP:Initial UE Context Setup Responseメッセージで応答する。
さらに、上記の手順を完了した後は、アクティブモードで回線交換フォールバックCSFB - 移動体着信呼で以前に説明したアクティブモードと同じですが、PS HOはありません。
以下に示す手順のステップ2から開始します。 これは、上記のリンクをたどって見つけたものの修正されたバージョン(ステップ1がなくなった)です。
Cの多次元配列
C言語は多次元配列を可能にします。 ここに多次元配列宣言の一般的な形式があります
たとえば、次の宣言は3次元の整数配列を作成します
2次元配列
多次元配列の最も単純な形式は2次元配列です。 2次元配列は、本質的に、1次元配列のリストである。 サイズ[x] [y]の2次元整数配列を宣言するには、次のように記述します
typeは任意の有効なCデータ型であり、arrayNameは有効なC識別子です。 2次元配列は、x個の行とy個の列を持つテーブルと考えることができます。 3つの行と4つの列を含む2次元配列aは、以下のように示すことができる
したがって、配列aのすべての要素は、a [i] [j]という形式の要素名で識別されます。ここで 'a'は配列の名前で、 'i'と 'j'は一意に識別する添え字です 'a'の各要素。
2次元配列の初期化
多次元配列は、各行に括弧で囲まれた値を指定することによって初期化することができます。 以下は3行の配列で、各行は4列です。
2次元配列要素へのアクセス
2次元配列内の要素は、添え字、すなわち配列の行インデックスおよび列インデックスを使用してアクセスされる。 例えば
上記のステートメントは、配列の3番目の行から4番目の要素を取得します。 上記の図で確認できます。 ネストされたループを使用して2次元配列を処理した次のプログラムを確認しましょう
上で説明したように、任意の次元数の配列を持つことができますが、作成する配列の大半は1次元または2次元です。
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は、以下のように示すことができる
したがって、配列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
ポインタとしての正式なパラメータ
ウェイ-2
サイズの配列としての正式なパラメータ
道 - 3
サイズの指定されていない配列としての正式なパラメータ
例
今度は、次の関数を考えてみましょう。これは、配列を別の引数と共に引数としてとり、渡された引数に基づいて、次のように配列を渡される数値の平均を返します
ご覧のように、配列の長さは、Cが仮パラメータの境界チェックを実行しないため、関数が関係する限り重要ではありません。
ウェイ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でポインターを理解していると仮定してみましょう。配列名は配列の最初の要素への定数ポインタです。 したがって、宣言では
balanceは&balance [0]へのポインタであり、これは配列のバランスの最初の要素のアドレスです。 したがって、以下のプログラムフラグメントは、pをbalanceの最初の要素のアドレスとして割り当てます
配列名を定数ポインタとして使用することは正当であり、その逆もあります。 したがって、*(残高+ 4)は残高[4]でデータにアクセスする正当な方法です。
最初の要素のアドレスを 'p'に格納すると、* p、*(p + 1)、*(p + 2)などを使用して配列要素にアクセスできます。 以下に、上で論じたすべての概念を示す例を示します
上記の例では、pはdoubleへのポインタです。つまり、double型の変数のアドレスを格納できます。 上記の例で示したように、pにアドレスがあると、* pはpに格納されているアドレスで利用可能な値を返します。
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は関数からポインタを返すこともできます。 これを行うには、次の例のようにポインタを返す関数を宣言する必要があります
ここで、10個の乱数を生成し、ポインタを表す配列名、つまり最初の配列要素のアドレスを使用してそれらを返す次の関数を考えてみましょう。
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番目のポインタのアドレスが格納されます。
ポインタへのポインタである変数は、そのように宣言されなければなりません。 これは、名前の前に追加のアスタリスクを置くことによって行われます。 例えば、次の宣言はint型のポインタへのポインタを宣言します
ターゲット値がポインタへのポインタによって間接的に指されている場合、その値にアクセスするには、アスタリスク演算子を2回適用する必要があります(下の例を参照)。
配列の詳細
配列はCにとって重要であり、もっと注意が必要です。 配列に関する以下の重要な概念は、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 |
---|---|
1 | Multi-dimensional arrays
C supports multidimensional arrays. The simplest form of the multidimensional array is the two-dimensional array.
|
2 | Passing arrays to functions
You can pass to the function a pointer to an array by specifying the array's name without an index.
|
3 | Return array from a function
C allows a function to return an array.
|
4 | Pointer 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は位置1004を指します。これは、現在の位置の次の4バイトである次の整数位置を指します。 この操作では、メモリ位置の実際の値に影響を与えることなく、ポインタを次のメモリ位置に移動します。 ptrがアドレスが1000の文字を指している場合、上記の操作は1001で次の文字が使用可能になるため、1001の位置を指します。
ポインタをインクリメントする
定数ポインタであるためインクリメントできない配列名とは異なり、変数ポインタはインクリメントすることができるので、配列の代わりにプログラム内のポインタを使用することをお勧めします。 次のプログラムは、変数ポインタをインクリメントして、配列の各後続要素にアクセスします
ポインタを減らす
ポインタを減分する場合も同じ考慮事項が適用されます。ポインタは、そのデータ型のバイト数を下に示すように減らします
ポインタの比較
ポインタは、==、<、>などの関係演算子を使用して比較できます。 p1とp2が、同じ配列の要素など、互いに関連する変数を指している場合、p1とp2を有意義に比較することができます。
以下のプログラムは、前の例を変更します。変数ポインタを指すアドレスが配列の最後の要素のアドレス以下である限り、変数ポインタをインクリメントします。これは&var [MAX-1]
ポインタの算術を理解するために、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
Subscribe to:
Posts (Atom)
Interfaces and their protocol stacks
インタフェースとそのプロトコルスタック 主要なネットワーク要素に精通した後、これら要素間のインタフェースをよりよく知る時期が来ています。 インタフェースは、MME、SGWおよびPGWが他のネットワーク要素(例えば、HSSまたはPCRF)と協働することを可能にする。 それらの...
-
モバイル加入者の識別 一般情報 ユニークな国際モバイル加入者アイデンティティ(IMSI)は、各(GSM、UMTS、およびEPS)システム内の各モバイル加入者に割り当てられるものとする。加入者識別機密性サービスをサポートするために、VLR、SGSNおよびMMEは、訪問移動加入...
-
Periodic TAU 周期的トラッキングエリア更新は、UEのネットワークへの利用可能性を定期的に通知するために使用される。 この手順は、定期的なトラッキングエリア更新タイマ(タイマT3412)によってUEにおいて制御される。 タイマT3412の値は、ATTACH ACCEP...
-
EPSモビリティ管理(EMM)状態は、モビリティ管理手順に起因するモビリティ管理状態を記述する。 アタッチおよびトラッキングエリアの更新手順。 仕様に記載されている2つのEMM状態があります。 EMM-DEREGISTERED EMM-REGISTERED EPS接続管...