投稿

ラベル(Linux)が付いた投稿を表示しています

Linuxシステムコール、POSIX mutex による排他制御

UNIX / Linux システムコール・プログラミング POSIX mutex による排他制御 mutex(ミューテックス)とは? mutex(ミューテックス)は、 Mut ual Ex clusion の略で訳せば相互排他となります。 Unix系のOSにはセマフォも存在していますが、セマフォとの違いとしては、 ・ミューテックスでは制御権を持てるのは1つだけ。 セマフォは複数の使用者を設定することが可能です。 セマフォで使用者を1つだけとした場合は、ミューテックスと同様の動作となります。このように0/1だけの操作となるようなセマフォ/ミューテックスはバイナリセマフォとも呼ばれます。 ・ミューテックスは所有者の概念を持っている セマフォでは、ロックするプログラムとアンロックするプログラムが別でも構わない。 (デッドロックの元になるので危険な実装なのでオススメはしない) しかし、ミューテックスでは所有者の概念があるためロックをかけた使用者しかアンロックできない。この部分がセマフォと異なる部分です。 これらの特徴から、ミューテックスはスレッド間の排他制御でよく利用されます。 ミューテックスを使ったロックは、ロック動作を行ったスレッドしかアンロックできません。 それでは、 早速コードを示します。 mutex.c #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <ctype.h> #include <unistd.h> pthread_mutex_t mutex; void* thread(void* arg); // スレッドエントリ // // Main thread. // int main(int argc, char **argv) { int ret; const char *arg1 = "Pneumonoultramicroscopicsilicovolcanoconiosis, Pneumonoultramicr...

Linuxシステムコール、POSIX スレッドの生成

UNIX / Linux システムコール・プログラミング POSIXスレッドの生成 スレッドとは? スレッドは、実行の単位ですがプロセスとは異なります。プロセスは、プロセスごとに独立した論理アドレス空間をもち、異なるプロセス間ではメモリの共有をしていません。 プロセスの生成に関しては下記を参照。  →  Linuxシステムコール、プロセスの生成 これに対してスレッドは、1つのプロセスのメモリ空間を共有する複数の実行単位となります。簡単に言ってしまえば、ある関数fx()を呼び出すときにスレッドとして呼び出すことでfx()を複数、同時並列的に実行できるようになります。 同様のことは fork()で別プロセスとして分岐し、fx()を呼ぶことで実現できますがfork()はプロセスのメモリイメージのコピー(実際にはコピーオンライトで異なる部分だけのコピーでその他は共有されます)が発生し、プロセス動作するためのスタック領域などが別個に確保されるためのコストが発生します。 スレッドは、このようなコストを必要としないという特徴があります。 また、スレッドはマルチコアのCPUの場合に特定のコアにスレッドを結びつけることも可能という特徴もあります。 また、通常c言語は、main() から始まりますが、この大本をメインスレッドとも表現します。 スレッドを動かしてみよう! それでは、実際にLinux上でスレッドを使ったコードについて解説していきたいと思います。 サンプルコードは下記のような処理を行います。 1.3つの新しいスレッドを、pthread_create() で生成します。  このとき、メインスレッドから起動時の引数として文字列を渡します。 2.それぞれのスレッドが同時並行で処理を行います。  このコードでは下記の2つの処理を実装しています。   スレッド関数1. 引数の文字列の長さ分タイマーウエイトを行う   スレッド関数2. 引数の文字列を大文字・小文字変換して返す 3.メインスレッドは、各スレッドの完了を待ち合わせます。  起動されたスレッドは終了時に、pthread_exit() を使って終了コードを通知します。  メインスレッドは、pthread_join() を使って各スレッドの終了状態を受け...

Beaglebone Black ネットワーク・ブート環境の構築

イメージ
Beaglebone Black ネットワーク・ブート環境の構築     Beaglebone Black networking boot via Network over USB. 前回記事、「 BeagleBone Black 起動SDカードの作成 」では、Linuxを起動できるSDカードを作成してBeaglebone BlackをLinux動作させる方法について紹介しました。 しかし、この方法ではカーネル周りを開発する場合に毎回開発PCでSDカードを作成し、Beaglebone BlackにSDカードを戻して起動、という手順を毎回ふまなければなりません。 また、SDカードを頻繁に抜き差しするため、SDカードスロットへの負荷も大きくなり、SDカードスロットが故障する原因ともなり得ます。 このため、実際の開発現場においてはターゲットボードをネットワーク経由でブートする環境を構築することが現実的です。 今回の記事は、実際にBeaglebone Blackをネットワーク経由でブートするための環境を構築する方法について紹介します。 なお、この記事の内容はUbuntuのバージョンなど「 BeagleBone Black 起動SDカードの作成 」で紹介した環境をベースにしています。 ネットワーク・ブートとは? ネットワーク経由でのブートとは、ターゲットであるBeagleBone Blackと開発ホスト(サーバー)をTCP/IPで接続します。実現のために、このネットワーク上では、2つの技術を利用します。 1つ目は、ネットワーク経由でカーネルイメージをダウンロードしてメインメモリに展開するための「 TFTP 」。 もう1つは、システムが起動するためのルートファイルシステムをネットワークから与えるための「 NFS 」です。 AM3359は、電源投入後ROMプログラムが動作し、U-Bootをメインメモリにロードします。ここまではSDカード起動と同様です。このU-BootはBeaglebone Black上のMMCでも、SDカードでも問題ありません。 このU-Bootの機能を使ってTFTPサーバーから、カーネルイメージをダウンロードします。TFTPとは、Trivial File Transfer Prot...

Linuxシステムコール、プロセスの生成

イメージ
UNIX / Linux システムコール・プログラミング プロセスの生成 Linuxのプロセスとは? Linuxでは、プログラムの実行単位がプロセスとして定義されています。 これまで、このシリーズでもプロセス間通信を取り上げてきましたが、そもそもプロセスとは何でしょうか? 今回は、このプロセスについて取り上げてみたいと思います。 さて、先程プログラムの実行単位がプロセスだと書きました。通常、我々はgccなどを使って作成された ”実行ファイル” をメモリに読み込んでプログラムを実行します。これがプロセスです。 簡単な”Hello World”を例題に説明します。 hello.c #include <stdio.h> int main(int argc, char** argv) { printf("Hello World\n"); } このプログラムをコンパイルします。     $ gcc hello.c -o hello とすると、実行ファイル hello が出来上がります。 実行するには、     $ ./hello とすれば、実行されます。 当然ですが、このときにナニが起きているのか? 今まで気にしたことは無いかもしれませんが、詳しく見てみましょう。 ”$ ./hello”では、実行ファイルをコマンドとして、シェルから実行しています。 このシェルというユーザーインターフェイスも1つのプロセスとしてメモリ空間に存在しています。 ユーザーが、”$ ./hello”と、入力するとシェルは、fork() というシステムコールを呼び出して別のプロセスのためのユーザー空間を生成します。 そして、exec()というシステムコールを使ってそのメモリ空間に実行ファイル”hello”を読み出して展開し、main()にジャンプすることで、実行ファイル”hello”が実行され、コンソールに"Hello World"が表示されます。 UNIX系のOSでは伝統的に fork()/exec() という2段階のシステムコールによってプロセスの生成を行います。 まず、fork()ですが、このシステムコールは呼び出したプロセスのコピーを作り出します。 実際のコードを見て...

Linuxシステムコール、INETドメイン ソケット

UNIX / Linux システムコール・プログラミング プロセス間通信(IPC)、ソケット通信/INETドメイン ソケット Unixドメイン ソケットとは? Unixドメイン ソケットは、ノード間のネットワーク通信を行うことができ、現代のインターネット環境の基盤技術の1つと言えます。 INETドメイン ソケットを利用することで実際のネットワーク上のプロトコルであるTCP/IPやUDP/IPを意識したプログラミングが可能になります。 ※今回のサンプルコードは、TCP/IPです。 基本的に、INETドメイン ソケットもUnixドメイン ソケットと同様の実装となりますが、異なるノード間での通信を実現するため、ネットワークアドレスやポート番号を意識する必要があります。 それでは、サーバー側のコードを以下に示します。 inet-dimain-server.c #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <netinet/in.h> #include <arpa/inet.h> // Make server socket. // int makeServer(int portNo) { int sfd; int ret; struct sockaddr_in serv; // Create server socket. if((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("ERROR:Server Socket()"); return -1; } // Bind socket memset(&serv, 0, sizeof(struct sockaddr_in)); ...

Linuxシステムコール、Unixドメイン ソケット

UNIX / Linux システムコール・プログラミング プロセス間通信(IPC)、ソケット通信/Unixドメイン ソケット Unixドメイン ソケットとは? Unixドメイン ソケットは、同一ノード内(1つのCPUで動作する1つのオペレーティング・システム内)で動作するプロセス間で、双方向の通信手段を提供します。 また、ソケットはクライアント/サーバー モデルで構成されており、1つのサーバーが複数のクライアントからの通信を受け入れる構造をとります。 まず、以下にサーバー側のサンプルコードを示します。 unix-dimain-server.c #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> // Make server socket. // int makeServer(char* sockName) { int sfd; int ret; struct sockaddr_un name; // Unlink, last running remove the socket. unlink(sockName); // Create server socket. if((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { perror("ERROR:Server Socket()"); return -1; } // Bind socket memset(&name, 0, sizeof(struct sockaddr_un)); name.sun_family = AF_UNIX; strncpy(name.sun_path, sockName, sizeof(name.sun_path) - 1); if ((r...

Linuxシステムコール、セマフォの使い方

イメージ
UNIX / Linux システムコール・プログラミング プロセス間通信(IPC)、セマフォ セマフォとは? セマフォ、聞き慣れない言葉ですが大昔の鉄道の信号機のことです。 単線区間で列車同士が衝突しないようにするため、信号機が使われました。 意味合い的には同様で、コンピューター内のある資源(メモリなど)に別々のプロセスが同時にアクセスしないようにするために利用します。 セマフォはSYSTEM V IPC です。 この、セマフォを利用することで複数のプロセスが同期して処理を進めることができます。 Linuxのセマフォは、セマフォ集合として生成して利用します。 このため、1つのセマフォ集合に複数のセマフォを含めることができ、Linuxのセマフォはカウンティングセマフォであるため、複数の許可を与えることも可能です。 ただし、この記事のサンプルコードは1つの集合に1つだけのセマフォ、許可数は1つだけとなっています。 まず、セマフォ生成のサンプルコードを示します。 seminit.c #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <stdio.h> #include <stdlib.h> union semun { int val; struct semid_ds *buf; unsigned short *array; }; int main() { key_t key; int semid; union semun arg; if ((key = ftok("sem.dat", 'S')) == -1) { perror("ftok"); exit(1); } /* create a semaphore set with 1 semaphore: */ if ((semid = semget(key, 1, 0666 | IPC_CREAT)) == -1) { p...

Bluetooth経由での BeagleBone Black ログインする

今回は、BeagleBone Black に Bluetooth 経由でログインするまでのメモ記事です。 Windows10のPCから、Bluetooth 経由で BeagleBone Black にログインします。 Linuxで Bluetooth を利用するときはほぼ同じような手順になります。 最近では、BeagleBone Black に無線機能が搭載されたボードが発売されています。 BeagleBone Black Wireless では、Wi-Fi と Bluetooth を利用することができます。 しかし、手元の BeagleBone Black では無線機能がないため、外付けで利用することになります。 準備: Bluetoothドングル  今回、利用したのはバッファローの BSBT4D09BK です。  この、BluetoothドングルをUSBポートに接続して利用します。  → バッファローのページへ 5V AC/DCアダプター  BeagleBone Black で外付けのデバイスを利用するときには必要なようです。  (BeagleBone Greenでは不要なような?)  HDMI出力時も必要になりますが、内部的にUSB給電では電力不足なのでしょうね。  モノは、手元にあった秋月電子の5Vのアダプタを使いました。 RootFS  RootFSは、BeagleBone 用のRootFSを持ってきてください。  Bluetooth関連のソフトウェアもインストール済みです。 ログインまで: 1. BeagleBone Black でBluetoothを開始します。  "bluetoothctl" コマンドで以下の操作を行います。  コマンドを実行すると、サブコマンドの受付状態になります。  以下のサブコマンドを投入します。     power on      discoverable on      agent on      default-agent  この状態で、コントローラーがON、他機から検出可能、  ペアリング可能な状態となります。  Bluet...

Linuxシステムコール、共有メモリの使い方

UNIX / Linux システムコール・プログラミング プロセス間通信(IPC)、共有メモリ 共有メモリとは? カーネルが管理するメモリ空間をユーザープロセスに ”見えるようにする” ことで、複数のプロセス間で同じメモリ空間を利用することができます。 プロセスからは通常のメモリと同様に見えるため、同じエリアに対しての同時書き込みなどについては、排他制御を行う、あるいはアトミックな操作とするなどの対応が必要になります。 共有メモリは SYSTEM V IPC です。 それでは、早速サンプルコードについて解説します。 今回のコードは2つのプログラムで構成されています。 shm_r.c 共有メモリは、shmget()システムコールにより共有メモリを取得します。このときの引数の指定で”ない場合は作成する”、パーミッションを与えるなどの指定を行います。生成された共有メモリにアクセスするため、shmat()システムコールでポインタを得るます。 以降、このプロセスはshmat()システムコールで得たポインタを通じ、自由に共有メモリにアクセスすることができます。 この、サンプルshm_r.cは、共有メモリを生成・アタッチすると1秒毎にメモリの更新をチェックし、更新された場合は内容を表示します。このときの更新内容が "Quit"であった場合、共有メモリをデタッチし、共有メモリを破棄します。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <unistd.h> #define DATA_SIZE 2048 int main(void) { int id; char *shmData; char data[DATA_SIZE]; // Shared memory create a new with IPC_CREATE if((id = shmget(IPC_PRIVATE, DA...

Linuxシステムコール、シグナルの使い方

UNIX / Linux システムコール・プログラミング プロセス間通信(IPC)、シグナル シグナルとは? プロセスに対して非同期のイベント通知を行います。 プロセス側でシグナルハンドラを定義することで、非同期通知を受けることができます。 Ctrl+C で、動作中のコマンド(プロセス)を停止できますが、Ctrl+C は SIGINT というシグナルを発生させてプロセスの停止を行っています。 また、シグナルは SYSTEM V IPC です。 どのようにシグナルを使うか、下記にサンプルコードを示します。 このサンプルコードでは、 SIGINT と SIGTSTP の2つを受け取るシグナルハンドラを記述しています。 シグナルとシグナルハンドラは、sigaction()システムコールを使って設定されます。 同様のシステムコールとして、signal()が存在しますが、現代ではsigaction()の利用が推奨されています。 また、実装バージョンやアーキテクチャによっても動作や構造体が異なる場合がありますので注意してください。 実行した状態で、Ctrl + c(SIGINT) を押してもメッセージは表示されますがプログラムは停止しません。 Ctrl + z(SIGTSTP) を押すとプログラムが停止するようになっています。 $ ./signal I'm working... ^CCatch SIGNAL[2]    <-- Ctrl + c key in. Work harder!              <-- Signal handler message. Don’t stop. I'm working... I'm working... ^ZCatch SIGNAL[20]   <-- Ctrl + z key in. We have a break.        <-- Signal handler message. It’s goiung stop. I've had enough! $ signal.c #incl...

Linuxシステムコール、メッセージキューの使い方

UNIX / Linux システムコール・プログラミング プロセス間通信(IPC)、メッセージキュー メッセージキューとは? いわゆるメッセージボックスのような動作を行う IPC です。 プロセス間で一意に識別できるメッセージキューに対してメッセージを書き込み、受け取りができます。 また、メッセージキューは SYSTEM V IPC です。 メッセージキューを使うためには、まずメッセージキューを作成してユニークなキューIDを作成する必要があります。msgget()というシステムコールでキューを作成します。 メッセージを送信するためには msgsnd()、メッセージを受信するためには msgrcv()、最後にメッセージキューを削除するために msgctl() を使います。 メッセージの受信側プロセスのサンプルコードを下記に示します。 #include <sys/types.h> #include <stdio.h> #include <sys/ipc.h> #include <sys/msg.h> #include <string.h> #include <unistd.h> #define MSGBUFSIZ 256 int main(int argc, char** argv) { int msqid; key_t msgkey; struct msgbuf{ long mtype; char mdata[MSGBUFSIZ]; }; struct msgbuf msgdata,*p; p = &msgdata; // Make Message queue key. msgkey = ftok("msgq.key",'X'); // Get Message queue ID. msqid = msgget(msgkey,IPC_CREAT|0666); // Message receive loop wile get "Quit" massage. while(1) { // Receive a Message. ...

IPC(Inter Process Communication) とは?

イメージ
IPCの基本: Linuxだけではなく、マルチタスクをサポートしたOSでは各タスク(=プロセス)が強調動作できるようにタスク間通信をサポートしています。  特に、仮想メモリをサポートし、カーネル空間とユーザー空間をプロテクション機構によって分断されたメモリ空間でユーザープロセスが動作するようなシステムでは、ユーザープロセス同士で直接データをやり取りすることができません。  また、FreeRTOSのように仮想アドレスでの動作では無いものの、複数スレッドの動作が可能となるような環境下では通信の確実性、つまり通信の途中でスケジューリングされてデータ転送が不完全な状態になる、といった事象をさけるためにもOSがタスク間通信をサポートしています。 Uinuxでは、Inter Process Communication = IPC としてサポートしています。  基本となるIPC関連のシステムコールには下記のものがあります。   ・メッセージキュー   ・共有メモリ   ・パイプ   ・ソケット   ・シグナル   ・セマフォ このうち、メッセージキュー、セマフォ、共有メモリは歴史的に SYSTEM V IPC と呼ばれ、ファイルシステムを利用しないIPCとなっています。 以下、それぞれの特徴について簡単に記述します。  メッセージキュー: いわゆるメッセージボックスのような動作を行う IPC です。 プロセス間で一意に識別できるメッセージキューに対してメッセージを書き込み、受け取りができます。  共有メモリ: カーネルが管理するメモリ空間をユーザープロセスに ”見えるようにする” ことで、複数のプロセス間で同じメモリ空間を利用することができます。 プロセスからは通常のメモリと同様に見えるため、同じエリアに対しての同時書き込みなどについては、排他制御を行う、あるいはアトミックな操作とするなどの対応が必要になります。 パイプ: コマンドのリダイレクションで使われるパイプです。 先のコマンドの標準出力を次のコマンドの標準入力にパイプでつなぐことでプロセス間の通信を行っています。 ソケット: インターネ...

BeagleBone Black 起動SDカードの作成

イメージ
BeagleBoen Blackとは? BeagleBone Black(以下BBBとします)は、TIとDigi-Keyの協力で開発されたBeagleシリーズの1つで、TIで開発しているARMプロセッサのAM3xxx系のCPUを搭載しています。 また、この記事もDigi-Keyの記事をベースに記述しています。 https://www.digikey.com/eewiki/display/linuxonarm/BeagleBone+Black Wikipedia Beagle Board より BeagleBoneは、オープンソースの理念に基づき設計されているため回路図が公開されています。よくBeagleBoneと比較されるRaspberryPiですが、こちらは最近ではI/Oなどの周辺部分を除き公式には公開されていません。また、Video周りなどのドライバに関してもバイナリ提供でソースコードは公開されていません。  BeagleBone の回路図は、GitHub にアップされています。   https://github.com/beagleboard/beaglebone-black/blob/master/BBB_SCH.pdf BeagleBone Black はボード上に512MBのRAM、4MBのMMC、SD-Cardスロット、USB、LAN、HDMIなどが搭載されていて、購入状態で MMC 上の Linux が起動できます。 今回の企画では、SDカード上にLinuxを構成して、BBB を起動するまでについて解説します。なお、起動時の RootFS は、Debian を使用します。 また、下記の説明では "sudo" の表記を省略していますので、適宜 "sudo" を使ってコマンドを実行するようにしてください。 追記:  ↓ネットワーク・ブートしたい場合  Beaglebone Black ネットワーク・ブート環境の構築 用意するもの: ・BeagleBone Black  ・開発用Linux PC(仮想PCでもOK)  ・3.3vUSBシリアル変換ケーブル    http://akizukidenshi.com/catalog/g/gM-0...