[日記] 「ふつうのLinuxプログラミング」を読んだ

2012/03/19

こんにちは。きんくまです。

ふつうのLinuxプログラミング」という本を読みました。
とても面白かったです。

書名にLinuxと入っているのですが、Unix系であるMacでも、一部をのぞいて基本OKです。
Macでうまく動かなかったら、ググったりするといいかも。

内容はどんなものかというと、Unixのコマンド(ls,mvとか)をCで実装しながら、システムの仕組みを学んでいくというものです。
といっても、プログラムがすごく複雑かというとそうでもなく、割と短めのシンプルなものがほとんどです。

本全体の3分の2を使って、システムの動作まわりを確認。
残りの3分の1を使って、httpサーバーを作るという流れになります。

私はネットワーク関係は、すでに別で勉強してたり、また他の本でやろうと思っているので、
この本のhttpサーバーの所は、ささっと流し読みだけしておきました。

もうちょっと内容について詳しく書くと、「カーネルって結局なんなの?」とか「プロセスって?」、「Cでのライブラリ?、gccって何なの?」などが書いてあります。
ひとつひとつについて、簡単にまとまっているので、概要をつかんでいくのにはすごく良い本だと思いました。

例えば、新しいプログラムを実行するのはどうやるのかというと、
「親プロセスからforkした子プロセスが新しいプログラムをexecする」
なんて書くとよくわからないかもしれないです。

簡単に書くと、「親が分裂、分裂してできた子供が新しいプログラムに上書きされる。」みたいなイメージでしょうか。
このあたりは、面白かったです。

あと個人的には、Cのプログラムを実際に書くときの作法というか、そんなのがなんとなく身に付いたような気がします。

LINEで送る
Pocket

[Terminal | ターミナル] TerminalからApacheをスタートするシェルスクリプト(Lion)

2012/03/10

こんにちは。きんくまです。

MacにはWebサーバーのApacheが最初から入っています。それで、そのメモです。
OSはlionです。

httpd.confの場所は以下にあります。設定が必要な場合はこれをいじればOKです。
/etc/apache2/httpd.conf

コマンドから起動

apachectlというコマンドがまず関係していて、man apachectlを見ると

NAME
       apachectl - Apache HTTP Server Control Interface

SYNOPSIS
       When  acting  in  pass-through  mode,  apachectl  can  take all the arguments available for the httpd
       binary.

       apachectl [ httpd-argument ]

とかなっています。パス通しモードだとhttpdに直接引数伝えるよ。となっているので、man httpdをひきます。httpdという名前はhttpを扱うデーモン(d) だと思われ。

NAME
       httpd - Apache Hypertext Transfer Protocol Server

SYNOPSIS
       httpd [ -d serverroot ] [ -f config ] [ -C directive ] [ -c directive ] [ -D parameter ] [ -e level ]
       [ -E file ] [ -k start|restart|graceful|stop|graceful-stop ] [ -R directory ] [ -h ] [ -l ] [ -L ]  [
       -S ] [ -t ] [ -v ] [ -V ] [ -X ] [ -M ] [ -T ]

長いオプションがあるのですが、今回関係するのは -k と -D のみです。

結論から先にいいますと以下のコマンドでTerminalからサーバーをスタートできます。
sudo使っているので、アカウントのパスワードがコマンド打った後から必要です。

sudo apachectl -D WEBSHARING_ON -k start

ストップしたいときは以下のコマンドです。

sudo apachectl -k stop

それで、WEBSHARING_ONというのはどこからきたかといいますと、
httpd.confの中にIfDefineではじまるWEBSHARING_ONという部分がありまして、
そいつを引っ張る必要があるようです。
このオプションを通せばそこからうまく設定を読みこんでくれるという感じです。

ちなみにGUIからだと
System Preference > Web Sharing
のチェックボックスを有効にしたり、無効にしたりすればOKです。

httpd-1

GUIから起動しているときに、httpdのプロセスを確認してみます。

kinkuma$ ps -ax | grep ht
 5958 ??         0:00.14 /usr/sbin/httpd -D FOREGROUND -D WEBSHARING_ON
 5961 ??         0:00.00 /usr/sbin/httpd -D FOREGROUND -D WEBSHARING_ON
 5996 ttys000    0:00.00 grep ht

こんな感じになっていて、 httpdというプロセスが WEBSHARING_ON というオプションつきで動いているのがわかります。 もうひとつのFOREGROUNDはhttpdのmanを見ると

       -D parameter
              Sets a configuration parameter which can be used with  sections in the configuration
              files to conditionally skip or process commands at server startup and  restart.  Also  can  be
              used  to  set certain less-common startup parameters including -DNO_DETACH (prevent the parent
              from forking) and -DFOREGROUND (prevent the parent from calling setsid() et al).

IfDefineのところをスキップするかそのまま進めるかを設定できます。
また-DNO_DETACHだと親からforkするのを防いだり、
-DFOREGROUNDだと親プロセスからsetsid()を呼ばれるのを防ぎます。
と書いてあるんだけど、このあたり今勉強中なのでまだよくわかりません、。

ちなみにコマンドからこの-DFOREGROUNDをつけてhttpdを起動したところ、その間だけコマンドの入力がかえらずに、サーバーが動いている状態になっていて、Ctrl+Cでコマンドを終了するとその場でサーバーも終了というふうになりました。たぶんマニュアルの通り、親からプロセスが切り離されていないためにこういう形になるってことかな?

シェルスクリプト

それで、今回のをシェルスクリプトにしたら便利だよなと思い作ってみました。

myapache

#!/bin/sh

starthttpd()
{
  sudo apachectl -D WEBSHARING_ON -k $1
}

stophttpd()
{
  sudo apachectl -k stop
}

if [ $# = 0 ] ; then
  echo "Usage: myapache [ start | restart | stop ]"
elif [ "$1" = "start" ] ; then
  starthttpd "start"
  echo "httpd is running..."
elif [ "$1" = "restart" ] ; then
  starthttpd "restart"
  echo "httpd restarted"
elif [ "$1" = "stop" ]; then
  stophttpd
  echo "httpd stopped"
fi

使い方としては、上の内容のmyapacheというテキストファイルを用意します。

/usr/local/bin

に移動して、実行権をつけます。

chmod 744 /usr/local/bin/myapache

こんな感じになっていれば大丈夫。うまくいかなかったらsudoとかつけてからコマンド入力するといいかも。

kinkuma$ ls -l /usr/local/bin/myapache
-rwxr--r--  1 kinkuma  admin  414 Mar 10 04:35 /usr/local/bin/myapache

ここまでで準備完了。
あとはスタートするときは、

myapache start

ストップするときは

myapache stop

再起動するときは

myapache restarrt

とコマンドを打てばOKです。

LINEで送る
Pocket

XcodeとSublime Text2でフォントのアンチエイリアスをなくす

2012/03/8

こんにちは。きんくまです。

最近Sublime Text2でアンチエイリアスを切って作業しております。
そんで、アンチエイリアスなしに慣れてくると、Xcodeでアンチありが見えづらいと感じてきました。
WinのMSゴシックアンチなしでプログラムを始めた身としては、こちらに慣れてしまっておりまして、、。
このあたりは好みの問題だと思うので、仕方ないですね、、。

なので、調べてみるとやはり方法はあったのですね。

Xcodeでアンチエイリアスなし

>> xcode4 – Xcode 4 – AppleAntiAliasingThreshold doesn’t work, so how to disable antialiasing? – Stack Overflow

terminalで以下のコマンドを打って、Xcodeを立ち上げ直せばOKです。

defaults write com.apple.dt.Xcode AppleAntiAliasingThreshold 24

no-antialias1

man defaultsと打ってマニュアルを見ると、書き方などが書いてありました。

defaultsの後に打つ サブコマンドとして、以下のものがあるみたいです。
read, read-type, write, rename, delete

なので、値を書き換えたかったら再びwriteを使って。読み込むならread。この値そのものを消したかったらdeleteという感じでしょうか。
今回のコマンドを試すときに、デフォルトの値をみたかったので、readを先にしてみたところ、そんな値はありませんぜ。という風に出たので、アンチありに戻したかったらdeleteコマンドを使えば大丈夫と思います。

Sublime Textでアンチエイリアスなし

コマンド + , (カンマ)を打って出てくる設定ファイルにfont_options:[no_antialias]を加えればOKです。
私の設定ファイルはこんな感じになりました。


{
	"color_scheme": "Packages/Color Scheme - Default/Blackboard.tmTheme",
	"font_options":
	[
		"no_antialias"
	],
	"font_size": 14,
	"font_face": "Andale Mono",
	"tab_size": 4,
	"word_wrap": true
}

no-antialias2

Flash Builderでアンチエイリアスなし

追記
同じように、Flash Builderでもできるのかなと思って調べてみるとやはりできました。

>> osx – How can I turn off anti-aliasing for the text editor in Flash Builder on the Mac? – Super User

defaults write org.eclipse.eclipse AppleAntiAliasingThreshold 24

そんで、デフォルトの白地テーマだとアンチなしではすごーく見えづらかったので、
SublimeとかAptanaにもあったこの黒地テーマの真似してカラーリングしてみました。

no-antialias3

LINEで送る
Pocket

[C] Sublime Text + SublimeClang でコード補完とか

2012/03/3

こんにちは。きんくまです。

Sublime Textを使っていて、
Cのヘッダーファイルをこれで見れたらいいよなー。と思い、検索したところどうやらプラグインがあるみたいです。

>> Sublime Forum • View topic – Autocomplete function names from external (.h) files

quarnsterさんという方のSublimeClangというものです。
>> SublimeClang

そんで、インストールしてみたところ、すごく便利だったので紹介です。

・コード補完ができる
・型や関数のところでOption +d, Option +dと押すと、ヘッダーファイルの定義の箇所にジャンプ
・Option + d, Option + i で、実装部分にジャンプ(見つかる場合)
・コードにエラーがあるとその場で四角い枠がつく

なんていう、機能がついてきます。

Clangって何か書店で見かけた単語だよなーと思ったら、Wikiによるとコンパイラ一部らしい。llvmっていうのとセット。
そういや、iOSのビルドするときもllvmっていう文字をよく見たような気が。でもよくわかんない。
Clang

SublimeClangのインストール方法

マニュアルに書いてある方法でやります。

1) Sublime Package Controlをインストール

ctrl+`を押して、Sublimeのコンソールを出す。

>> このページのコマンドをうって、アプリを立ち上げ直す。

2) cmd+shift+P を押して子ウインドウを出してPackage Control: Install Packageを選択

3) SublimeClang を選択するとインストールが自動で始まる

LINEで送る
Pocket

[Terminal | ターミナル] manコマンドとか

2012/02/29

こんにちは。きんくまです。

最近Terminalをよく使ってるんですけど、なんていうか何でもアリなんだなと思ってきています。

例えば、16進数でバイナリを見るコマンドが用意されてたり

kinkuma$ hexdump samplefile
0000000 cf fa ed fe 07 00 00 01 03 00 00 80 02 00 00 00
0000010 0d 00 00 00 20 06 00 00 85 00 20 00 00 00 00 00
0000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45
0000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000040 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00

似たコマンドでodとかもあったり。

文字コード変換はiconvがデフォルトで使えて、nkfというのもあるのですけど、homebrewとかで簡単にインストールできたり。

ファイルの更新日を変更したかったら、touchコマンドというのがあったり。

そんで、今日気がついたのだけど、ヘルプを見るmanコマンドというのがあるのですが、
てっきりunixのコマンドだけのヘルプなのかなと思ったら、Cの標準関数も引けるんですね。知らんかったですよ。
こんな感じに。

kinkuma$ man memcpy

ネットワーク系でhtonlという関数があるんですけど、こういうマニアック(?)なのも載ってるんですね。

関数の使い方に辞書使ったり、ネットで検索してたりしたのだけれど、関数自体の使い方になれてくれば、「あれの引数と戻り値なんだっけ? ヘッダファイルは何いれとけばいいの?」みたいな時にこれだけでなんとかなりそうな感じです。

FTP用のCUIコマンドっていうかCUIアプリでncftpというのがあるんですけど、ファイルを1個アップするだけだったりするときに便利です。
私はFTPのGUIはFilezilla使っていまして。いくつものディレクトリに分かれているときとかは、こっちの方が慣れているし、やりやすいのですが、ファイルの数が少量だったりするとCUIは便利かもしれないですね。

あとは、wgetとcurlというネットワーク上からファイルをダウンロードするコマンドがありまして、ブラウザ経由でファイルを保存するよりは割と便利だったりします。
テストサーバーから自分の持っていないファイルを引っ張るときとか。

それで、Terminalのこの手のコマンド見つけては「うは。こんなのもあるのか!?  なんか節操ないなー」と苦笑いしつつも、「おお、unixすげえなー」と思ったりしてます。

今までこういうちょっとした作業用に「何かフリーのGUIアプリないかなー?」と検索していたのですけど、「これCUIコマンドでないの?」みたいに検索することが増えてきている次第です。

■追記

manコマンドで候補がいくつか出てくるときに、どうするかについてです。
acceptというsocketのコマンドをひきたいとして。

そのままman accept とコマンドを実行するとアップルのcupsaccept(8) というコマンドが引かれてしまいます。
なので、-fオプションをつけて、man -f acceptとすると候補のリストが出ます。

BIO_s_accept(3ssl), BIO_set_accept_port(3ssl), BIO_get_accept_port(3ssl), BIO_set_nbio_accept(3ssl), BIO_set_accept_bios(3ssl), BIO_set_bind_mode(3ssl), BIO_get_bind_mode(3ssl), BIO_do_accept(3ssl) - accept BIO
accept(2)                - accept a connection on a socket
accept(8), cupsaccept/cupsreject(8) - accept/reject jobs sent to a destination
femail(8)                - accept mail on behalf of a real MTA
getstr(3x), getnstr(3x), wgetstr(3x), wgetnstr(3x), mvgetstr(3x), mvgetnstr(3x), mvwgetstr(3x), mvwgetnstr(3x) - accept character strings from curses terminal keyboard

今回の場合はソケットの関数をひきたかったので、accept(2)が正解のようです。なので、括弧の中のものをオプションとしてコマンドを実行。

man 2 accept

そうすると目的のものを引くことができました!

ACCEPT(2)                   BSD System Calls Manual                  ACCEPT(2)

NAME
     accept -- accept a connection on a socket

SYNOPSIS
     #include 

     int
     accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
以下マニュアルがつづく

■さらに追記
Wikiによると、この番号はカテゴリだそうで。

章	内容
1	汎用コマンド
2	システムコール
3	Cライブラリ 関数
4	特殊なファイル(主に /dev にあるデバイス)
5	ファイル形式とその使用法
6	ゲーム
7	その他
8	システム管理コマンドとデーモン

今回は2をひいたので、これはUNIXのシステムコールのカテゴリということになります。

LINEで送る
Pocket

[C] base64のメモ

2012/02/29

こんにちは。きんくまです。

文字コードの本を読んでいます。

>> プログラマのための文字コード技術入門 (WEB+DB PRESS plus)

どうやって文字を表すのかということや、ビットを駆使してなんとか文字を詰め込んだりしてたことがわかって面白いです。

それで、base64という符号化の仕組みが本の中で出てきました。

>> Base64

名前を聞いたことがあっても、どういうものかいまいちわからなかったので、調べてみました。
そんで実際にエンコードしてみようと思い、プログラムを書いてみました。

#include <stdio.h>
#include <string.h>

int charToBinary(char s, char *binstr, int offset){
	int encoded;
	int i;
	for(i = 0; i < 8; i++){
		encoded = ((s >> (7 - i)) & 0x1) == 0 ? '0' : '1';
		binstr[i + offset] = encoded;
	}
	return 0;
}

int sixbitToInt(char *binstr, int offset){
	int i, n, bit, cnt;
	n = 0;
	cnt = 0;
	for(i = offset; i < offset + 6; i++){
		bit = binstr[i] == '0' ? 0 : 1;
		n += bit << (5 - cnt);
		cnt++;
	}
	return n;
}

int main(int argc, char const *argv[])
{
	char msg[7] = "hello";
	char binstr[64];

	memset(binstr, '0', sizeof(binstr));

	int i, j, b64;
	for(i = 0; i < 7; i++){
		charToBinary(msg[i], binstr, i * 8);
	}

	printf("input 8bit : ");
	for(i = 0; i < 8; i++){
		for(j = 0; j < 8; j++){
			printf("%c", binstr[i * 8 + j]);
		}
		printf(" ");
	}
	printf("\n");

	printf("input 6bit : ");
	for(i = 0; i < 9; i++){
		for(j = 0; j < 6; j++){
			printf("%c", binstr[i * 6 + j]);
		}
		printf(" ");
	}
	printf("\n");

	printf("output: ");
	for(i = 0; i < 9; i++){
		b64 = sixbitToInt(binstr, i * 6);
		printf("%d ", b64);
	}
	printf("\n");
	return 0;
}

hello という文字列をエンコードしたらどうなるかというものです。
出力はこうなります。

input 8bit : 01101000 01100101 01101100 01101100 01101111 00000000 00000000 00000000 
input 6bit : 011010 000110 010101 101100 011011 000110 111100 000000 000000 
output: 26 6 21 44 27 6 60 0 0 

この本やWikiにもある通り、

1) 各1文字を8ビットで表す
2) それを6ビットずつに切り分ける
3) その数値と変換表を照らし合わせる
4) それを4文字ずつのセットにして、足りなかったら=で埋める

となっています。

helloをエンコードした後に、wikiの変換表を見ると次のようになります。
26 -> a, 6 -> G, 21 -> V, 44 -> s, 27 -> b, 6 -> G, 60 -> 8

つなげてかくと
aGVsbG8

全部で7文字なので、1文字分=で埋めれば
aGVsbG8=

となります。

オンラインでbase64に変換できるサービスがあったので、試してみたところ同じように出力されました。

>> Base64 Online – base64 decode and encode

LINEで送る
Pocket

[C] Cでのバイトとビット入門

2012/02/22

こんにちは。きんくまです。

Cの基礎を勉強しておりまして、バイトとビットについて理解が必要になりました。
なので、その成果を書こうと思います。読んでいる方の参考まで。

ビット

ビットは0と1を表します。ビットは普通2進数を表すのに使われます。
具体例です。

2進数 10進数 ビット数
0 0 1
1 1 1
10 2 2
11 3 2
100 4 3
111 7 3
1000 8 4
1010 10 4
1111 15 4

4ビットは10進数で0から15までを表すことができます。
だから、16種類の数字を表すことができます。

ところで、16進数についてです。
Cでは16進数は値の前に0xをつけて表します。それでは、16進数の列を上の表につけてみましょう。

2進数 10進数 16進数 ビット数
0 0 0x0 1
1 1 0x1 1
10 2 0x2 2
11 3 0x3 2
100 4 0x4 3
111 7 0x7 3
1000 8 0x8 4
1010 10 0xA 4
1111 15 0xF 4

バイト

バイトは普通8ビットを表します。
バイトが10進数でどのくらいの範囲を表すかわかりますか?
前の項目で4ビットは0から15までを表すと書きました。
それで、8ビットは4ビット+4ビットなので、こんな感じに表すことができます。
16 * 16 = 256
だから、8ビットは10進数で0から255までの、256種類の数字を表せます。

では、さきほどの表を8ビットに拡張してみましょう。

2進数 10進数 16進数 ビット数
0 0 0x00 1
1 1 0x01 1
10 2 0x02 2
11 3 0x03 2
100 4 0x04 3
111 7 0x07 3
1000 8 0x08 4
1010 10 0x0A 4
1111 15 0x0F 4
10000 16 0x10 5
10001 17 0x11 5
11111 31 0x1F 5
100000 32 0x20 6
111111 63 0x3F 6
1000000 64 0x40 7
1111111 127 0x7F 7
10000000 128 0x80 8
11111111 255 0xFF 8

んー。ぱっと見、難しそうです。でも、少しずつ見ていけば簡単にわかります。
10進数64を見てみましょう。

2進数 10進数 16進数 ビット数
1000000 64 0x40 7

最初に2進数を2つに分けます。4ビットごとにしました。
100 – 0000
左側は100。これは16進数で0x4です。
右側は0000。これは16進数で0x0です。
だから、16進数では、これは0x40と表されます。

ASCII表

ASCII 表は文字コードの表です。
>> ASCII Table and Description

ASCIIコードを前に作った表に足してみましょう。

2進数 10進数 16進数 ASCII文字 ビット数
0 0 0x00 NUL 1
1 1 0x01 SOH 1
10 2 0x02 STX 2
11 3 0x03 ETX 2
100 4 0x04 EOT 3
111 7 0x07 BEL 3
1000 8 0x08 BS 4
1010 10 0x0A LF 4
1111 15 0x0F SI 4
10000 16 0x10 DLE 5
10001 17 0x11 DC1 5
11111 31 0x1F US 5
100000 32 0x20 Space 6
111111 63 0x3F ? 6
1000000 64 0x40 @ 7
1000001 65 0x41 A 7
1010001 97 0x61 a 7
1111111 127 0x7F DEL 7
10000000 128 0x80 8
11111111 255 0xFF 8

10進数で127より上では、いくつかの拡張ASCII表の種類があるようです。
だから、今回は記入しませんでした。

さて、文字Aの行を見てみます。

2進数 10進数 16進数 ASCII文字 ビット数
1000001 65 0x41 A 7

文字Aは10進数で65で、16進数で0x41です。

Cでの文字と整数

前の項目では、文字コードと10進数、16進数の関係を書きました。
それをもとに、Cのコードを書いてみます。

#include <stdio.h>

int main(int argc, char const *argv[])
{
	char c, c2;
	int i, j;

	c = 'A';
	printf("c is %c. character code is %d, binary is %x\n", c, c, c);
	//出力
	//c is A. character code is 65, binary is 41

	i = 97;
	printf("i is %c. character code is %d, binary is %x\n", i, i, i);
	//出力
	//i is a. character code is 97, binary is 61

	//char to int
	j = c;
	printf("j is %c. character code is %d, binary is %x\n", j, j, j);
	//出力
	//j is A. character code is 65, binary is 41

	//int to char
	c2 = i;
	printf("c2 is %c. character code is %d, binary is %x\n", c2, c2, c2);
	//出力
	//c2 is a. character code is 97, binary is 61

	return 0;
}

1バイトより上について

1バイトについて、今回は書きました。でも、普段のプログラミングでは1バイト以上を扱うことがあります。
なので、次回の記事ではそのことについて書こうと思います。

LINEで送る
Pocket

ページトップへ戻る