> > プロセス実行開始時間: getrusage(2)
> > (特定の子プロセスの場合は wait3(2) ないし wait4(2))
>
> いかん、これ嘘でした。
> 正しくは下記の通り (Linux でしか通用しません)
>
> 1. /proc/$PID/stat の 22 番目の欄が、起動後 HZ を単位として
> 計った開始時刻。この値を start_time とする
> 2. そのマシンの uptime は /proc/uptime 中の 1 番目の欄から求まる。
> 単位は 秒。この値を uptime とする
> 3. HZ の値は #include <asm/param.h> で得られる。
> 4. 上記の結果から
> (time(NULL) - uptime) + start_time / HZ
> で、開始時刻が time_t 型の値として得られるので、
> これを ctime() 等の関数で文字列に直せば良い。
>
> 詳しくは procps のソース参照。
> BSD系の方が簡単だな〜
ご意見ありがとうございました。
さっそく試してみました。
getuidを実行したら現在プロセスを実行しているユーザの
uid,gidを取得してしまいました。
私の質問の内容が悪かったみたいです。すみません。
改めて,教えてください。
取得したいuid,gidは各プロセスごとの実行ユーザのuid,gidです。
もう2つお聞きします。
1.プロセスごとの実行時間はどのようにしたら取得できるのでしょうか?
2.Linuxではプロセス情報の管理をtask_struct構造体で管理していると
とあるサイトで紹介されていましたが,この構造体は使用しなくても
プロセスごとの情報を取得できるということでしょうか?
task_struct構造体についてご存知な点がありましたら
ご意見よろしくお願い致します。
よろしくお願い致します。
> プロセス実行開始時間: getrusage(2)
> (特定の子プロセスの場合は wait3(2) ないし wait4(2))
いかん、これ嘘でした。
正しくは下記の通り (Linux でしか通用しません)
1. /proc/$PID/stat の 22 番目の欄が、起動後 HZ を単位として
計った開始時刻。この値を start_time とする
2. そのマシンの uptime は /proc/uptime 中の 1 番目の欄から求まる。
単位は 秒。この値を uptime とする
3. HZ の値は #include <asm/param.h> で得られる。
4. 上記の結果から
(time(NULL) - uptime) + start_time / HZ
で、開始時刻が time_t 型の値として得られるので、
これを ctime() 等の関数で文字列に直せば良い。
詳しくは procps のソース参照。
BSD系の方が簡単だな〜
> ところで、宣言から2週間。1日たりとも「予定外の飲酒」されてないのでしょうか。
> だとしたら、それはすごいですね〜。
ないです(すごいでしょ)。12/9は予定された飲み会でしたのでその時は
飲みましたけど、それ以外は全く飲んでません。
> あるいは週5くらいで飲み会の連続だったとか;-)
まあ今週は、これから2回飲み会があるんですけどね。
いやあ、やればできるもんですね。我ながらちょっとびっくり。
ところで、宣言から2週間。1日たりとも「予定外の飲酒」されてないのでしょうか。
だとしたら、それはすごいですね〜。あるいは週5くらいで飲み会の連続だったとか;-)
#あっと言う間にスレッドの層に埋もれてくのでたまには書きまなくちゃと.....
実行ファイル名: readlink(2) システムコールで "/proc/プロセスID/exe" を読む
プロセスを実行しているUID: getuid(2)
プロセスを実行しているGID: getgid(2)
プロセス実行開始時間: getrusage(2)
(特定の子プロセスの場合は wait3(2) ないし wait4(2))
詳しい使い方は、マニュアルを読んでください。
"/proc/プロセスID/exe" だけは、Linux 固有です。
それ以外は他の UNIX 系 OS でもだいたい使えます。
getuid(2)あたりを知らないという状態なら、UNIXのシステムコール
関係の書籍を一冊購入して読まれることをお勧めします。
定番は Richard Stevens の「詳解UNIXプログラミング」
(ISBN 4-89471-319-5) です。getuid()/getgid() は14ページ目に
出てきます。
教えてください。
C言語でLinuxのプロセス情報(実行ファイル名,プロセスを実行しているUID,
プロセスを実行しているGID,プロセス実行開始時間)
を取得する方法がわかりません。
/proc/<数字>/ ディレクトリ配下に欲しい情報がすべてあるのでしょうか。
あるのであれば,どのようなソースを書けば取得できるのでしょうか?
よろしくお願い致します。
>> scanf の %g は float 型(へのポインタ)を要求します。
> ここでは double 型(へのポインタ)を渡しているので誤りです。
> scanf で double を読み込む場合の記述方法、書いてもいいけど、
> 自分で探してみましょう > ishikawa さん。
ありがとうございます。
%lgですね。
とゆーかscanfがstdinのファイルポインタを読み込むってことも始めて知りました。(汗
もうちょっと調べてから質問するべきでしたね。
> > intとlong longがそろって64bitじゃ、
> > 32bitを扱う整数型がなくなっちゃいますよね?困らないかな?
> Cray の昔のスーパーコンピュータは、short/int/long すべて 64bit
> だった筈です。(Cray には long long はなかったと思いますが)
へぇ。それはまた...豪快なことしてますねぇ。
> 規格上許されている以上、そういう処理系もありってことで。
確かに規格上許されてはいますよね。
そのsuper computer上で整数型に大きさを指定することには意味がないですねぇ。
常にintを使えって言ってるんですね。
その場合、16bitや32bitでdataを扱いたいときはbit fieldでも使うんですかねぇ。
> > > double d;
> > > scanf("%g", &d);
> > > はうまく動かないので注意が必要です。
> > で、これはなんで動かないんでしょうか?
>
> ポインタだから。
御意。
と言ってしまってよいのでしょうか?
scanf の %g は float 型(へのポインタ)を要求します。
ここでは double 型(へのポインタ)を渡しているので誤りです。
scanf で double を読み込む場合の記述方法、書いてもいいけど、
自分で探してみましょう > ishikawa さん。
> ありゃ、場所によっては本屋でも入手できるんですね。こりゃまた失礼しました。
池袋のジュンク堂は特殊な書店なので、あまり失礼じゃないかも。
本屋が好きで、行ったことがない人は、機会があれば一度行って
みるべきだと思います。僕はたまげました。
売場面積世界一らしいっす。
> > double d;
> > scanf("%g", &d);
> > はうまく動かないので注意が必要です。
> で、これはなんで動かないんでしょうか?
ポインタだから。
> 売れいきがいいから、削って、正規の規格書を買わせようという魂胆?
> (と邪推してみたり…)
邪推ですが、私も同じように考えちゃってみたり。
> >> 規格書って本屋さんに売ってるんですかね?
>
> 東京近郊にお住まいなら、池袋のジュンク堂が、かなり大量の規格書を
> 置いています。(全部じゃないと思いますが)
ありゃ、場所によっては本屋でも入手できるんですね。こりゃまた失礼しました。
> 「JIS X 3010:1993 プログラム言語C」は8000円で買えるようです。
>
> http://www.webstore.jsa.or.jp/webstore/Com/FlowControl.jsp?lang=jp&bunsyoId=JIS+X+3010%3A1993&dantaiCd=JIS&status=1&pageNo=0
8000円ですか。。それだったらなんとか買えそうですね・・。(ちょっと迷うけど・・)
(ぱ)さん、774Rさんありがとうございました。分かりやすかったです。
> 一方 scanf() のマニュアルには、char 型や float 型(へのポインタ型)を
> 受け取るフォーマット文字があります。
> double d;
> scanf("%g", &d);
> はうまく動かないので注意が必要です。
で、これはなんで動かないんでしょうか?
> 昔は「JISハンドブック」のプログラム言語編を1万円ちょっとで買うことができ、
> この中にはCやらPascalやらAdaやらFORTRANやらの規格書が入っていたのですが、
> 2001年度の改訂でごっそり削られ、現在は入手できません。
がーん、そうだったのか…
ここ数年、探してもプログラム言語編だけないので変だなあと
思ってました。
# C やら Pascal やら Ada やら Fortran やら POSIX.1 やらの入ってる
# バージョンは持ってはいますが… 最近の改訂版が欲しい…
ショック…
なんででしょう?
売れいきがいいから、削って、正規の規格書を買わせようという魂胆?
(と邪推してみたり…)
>> 規格書って本屋さんに売ってるんですかね?
東京近郊にお住まいなら、池袋のジュンク堂が、かなり大量の規格書を
置いています。(全部じゃないと思いますが)
名古屋にもああいう本屋が欲しいっす。
> long longとintが同じ大きさになるような処理系って、
> 出てくることはないと思うんですけど、そういうのって予定されてましたっけ?
> intとlong longがそろって64bitじゃ、
> 32bitを扱う整数型がなくなっちゃいますよね?困らないかな?
> それにlongの居場所もないですし。
Cray の昔のスーパーコンピュータは、short/int/long すべて 64bit
だった筈です。(Cray には long long はなかったと思いますが)
規格上許されている以上、そういう処理系もありってことで。
> 発言本文1行目が1インデントされているように見えますが、
> 気のせいですか?<PRE> 内部に1スペース置かれてますね。
気のせいではありません。仕様です(とか言ってみる)。
この掲示板はOTDのレンタル掲示板です。
この掲示板では、OTDのカスタマイズ機能を使って無理やり投稿内容を
<PRE>で囲んでいるわけです。投稿内容そのものは、OTD側のサーバで
所定の位置に展開されますが、その際、なにしろむこうは<PRE>で囲むことなんか
想定していないものだから、行頭に半角スペースをひとつ突っ込んでくれるのです。
<PRE>の中なのに余計な<br>が入っているのもそのためです。
あしからずご了承ください。
> 「JIS X 3010:1993 プログラム言語C」は8000円で買えるようです。
>
> http://www.webstore.jsa.or.jp/webstore/Com/FlowControl.jsp?lang=jp&bunsyoId=JIS+X+3010%3A1993&dantaiCd=JIS&status=1&pageNo=0
げげ。失礼しました。
たしか昔はもっと高かったように思ったのですが…
またもやLANの関係で会社のパソコンでインターネットがダメになったので、
自前で接続することにしました。(毎月お金が羽をつけて飛んでいくけど・・・)
> ・プログラマの気持ちとしては %c に char 型 (8bit 型) を渡しているつもり。
それに加えて文字リテラルがint型というのが、更に問題をややこしくしているのかも。
%cフォーマットは多分、こちらのデータも想定しているような気がしません?
久しぶりの書き込みが横レスで申し訳ないです。(_o_)
発言本文1行目が1インデントされているように見えますが、
気のせいですか?<PRE> 内部に1スペース置かれてますね。
まあいいけど。
> printf("%u\n",a); /* 実行結果:177 */ /* 汎整数拡張によりaの値がint型に変換
> 1011 0001 → 0000 0000 1011 0001になる
> 16進数で表すと0x00B1、10進数で177になる。
> %uによってunsigned型に変換する。
> 0000 0000 1011 0001 = 0x00B1 = 177 →
> もとからunsignd型なので変換の必要性なし。
> よって177が出力。正解。 */
後者の「変換」というのはちと語弊があるかも。
汎整数拡張により a の値が int 型に変換される -> 正しい。
そのとおり 0xb1->0x00b1(0x000000b1) に変換されます。
(a が unsigned char 型だから)
%u は 0x00b1(0x000000b1) という値を受け取ります。
この値を unsigned int 型と「解釈し」、文字に「変換し」 177 と出力します。
別件。
既に(ぱ)さんもかかれていますが printf("%c", a); の場合
・プログラマの気持ちとしては %c に char 型 (8bit 型) を渡しているつもり。
・でもコンパイラは勝手に int 型 (16/32bit 型) に変換して渡している。
この変換において
signed char なら 0xb1->0xffb1(0xffffffb1) に変換
unsigned char なら 0xb1->0x00b1 (0x000000b1) に変換
がされます (既述)
printf() の内部の %c の処理ルーチンは、上記の「勝手に行われる変換」
すなわち汎整数変換について知っているため、
・ %c に対応する値として int 型を取り出し
・その値の下位 8bit を表示
します。
printf() のマニュアルを見ると
%c に対応する型は int 型
%g に対応する型は double 型
と書いてあります。
char/short/float を受け取るフォーマット文字はありません。
その理由は(ぱ)さんの説明のとおりです。
一方 scanf() のマニュアルには、char 型や float 型(へのポインタ型)を
受け取るフォーマット文字があります。
double d;
scanf("%g", &d);
はうまく動かないので注意が必要です。
# char は必ずしも 8bit 型とは限らないとか
# int は必ずしも 16/32bit 型とは限らないとか
# その辺は省略中。
> > 売ってません。日本規格協会から取り寄せる必要があります。3万円くらいします。
> > 昔は「JISハンドブック」のプログラム言語編を1万円ちょっとで買うことができ、
> > この中にはCやらPascalやらAdaやらFORTRANやらの規格書が入っていたのですが、
> > 2001年度の改訂でごっそり削られ、現在は入手できません。
> 高いですね・・・、買えそうにないです、今バイトしてないし・・。
> バイトしなければ。
「JIS X 3010:1993 プログラム言語C」は8000円で買えるようです。
http://www.webstore.jsa.or.jp/webstore/Com/FlowControl.jsp?lang=jp&bunsyoId=JIS+X+3010%3A1993&dantaiCd=JIS&status=1&pageNo=0
> > 2.暗黙の汎整数変換
> これは可変引数にしか通用しないんですか?
おそらくこれを理解するには、ANSI-C以前の古いCから理解したほうが
よいかと。
かつての(ANSI-C以前の)Cでは、intより小さい整数型が式の中に登場したら
片っ端からintに変換していました。また、float型は片っ端からdoubleに
変換していました。だから、式の中に現れるのは実質intとdoubleとポインタ
だけになり、その分コンパイラの手が抜けたわけです。
# だから単なるfloatとfloatの足し算でも、いったんdoubleに変換してから
# 行われました。
また、今のCでは、こんな形でプロトタイプ宣言を行いますが、
void func(int a, double b);
古いCではこんなふうに書きました。
void func();
おかげで引数の数や型をコンパイラがチェックしてくれなくてはまることも
多かったのですが、それだけではなくて、たとえばこの関数をこんな形で
呼び出したとして、
func(c, f);
cがchar, fがfloatだった場合、もし型拡張を行わなければ引数が正しく
渡らないことになります。これでは使いにくくてたまりません。
なにしろ昔のCでは、三角関数のsin()も
double sin();
とだけ宣言されていたわけで「sin()にfloat型を渡したら誤動作しちゃった」
というのではさすがにびっくりするでしょう。
古いCでは、intより小さい整数型は片っ端からintに、doubleより小さい
実数型は片っ端からdoubleに変換することで、こういった問題を回避していた
わけです。
ANSI-Cになって、プロトタイプ宣言が導入され、コンパイラが呼び出し側で
型変換を行うことができるようになりました。ですからプロトタイプ宣言を
書けば、intより小さな型でもそのまま渡すことができます(まあ具体的に
どう実装するかは処理系に依存しますが)。
でも、printf()のような可変長引数を取る関数の場合、可変部の引数については
プロトタイプ宣言が効かないため、従来の、「片っ端からint/doubleに拡張」
という変換が行われているのです。
> > 2.暗黙の汎整数変換
> これは可変引数にしか通用しないんですか?
引数が可変でなく、プロトタイプ宣言のある関数呼び出しなら、
汎整数拡張は行われない可能性があります。
この説明は始めると長くなるので、別便で。
> > しかし %c は与えられた引数の下位8ビットだけを取り扱うため
> > 0x00b1 でも 0xffb1 でも表示は b1 の部分だけ見て行われます。
>
> これってbig-endianだったらffかb1の部分を見て行われるんですね?
> (endianって言う単語はここの書き込みででてたので速攻で調べただけです、間違い
> だったら申し訳ない)
うーん、本多さんの話は、%cにlong longを渡すという「本来やっちゃいけないこと」
をやった場合の話であって、%cにintを渡すのは普通にやってよいことの話ですから、
そういうことをやっている分にはendianは影響しません(変なことをしないのに
endianによって違う動きをするようでは、Cは欠陥言語になっちゃいます)。
ここではprintf()には正しくintが渡っていて、%cはendianによらず数値的に
見たときの下位8bitを見るので「0x00b1 でも 0xffb1 でも表示は b1 の
部分だけ見て行われます」。
> とありますが%cは8ビットを取るんじゃないんですか?
%cはスタックからintを取り出し、その下位8bitを使用します。
> とあります。ぶっちゃけ、long double > double > float > 整数 の順で、
> 精度の高いほうに合わせよう、ということです。
そうでしたか、どうもありがとうございます。
> 売ってません。日本規格協会から取り寄せる必要があります。3万円くらいします。
> 昔は「JISハンドブック」のプログラム言語編を1万円ちょっとで買うことができ、
> この中にはCやらPascalやらAdaやらFORTRANやらの規格書が入っていたのですが、
> 2001年度の改訂でごっそり削られ、現在は入手できません。
高いですね・・・、買えそうにないです、今バイトしてないし・・。
バイトしなければ。
> 価格を考えると、K&Rでいいんじゃないかと思いますが…
> たとえば型変換がらみのことは、p.240〜に記述があります。
高いですね・・・、買えそうにないです、今バイトしてないし・・。
K&Rですか、こっちも検討しておきます・・。
> これってdouble型の場合どうなるんでしょうか?
規格書にはこの直前にその説明がありまして、
| まず、一方のオペランドが型long doubleをもつ場合、他方のオペランドを
| long doubleに型変換する。
| そうでない場合、一方のオペランドが型doubleをもつならば、他方のオペランドを
| doubleに型変換する。
| そうでない場合、一方のオペランドが型floatをもつならば、他方のオペランドを
| floatに型変換する。
とあります。ぶっちゃけ、long double > double > float > 整数 の順で、
精度の高いほうに合わせよう、ということです。
> それと他のとこでも質問したら規格書規格書ってでてくるんですが、
> 規格書って本屋さんに売ってるんですかね?
売ってません。日本規格協会から取り寄せる必要があります。3万円くらいします。
昔は「JISハンドブック」のプログラム言語編を1万円ちょっとで買うことができ、
この中にはCやらPascalやらAdaやらFORTRANやらの規格書が入っていたのですが、
2001年度の改訂でごっそり削られ、現在は入手できません。
> なんか欲しくなってきました・・。
価格を考えると、K&Rでいいんじゃないかと思いますが…
たとえば型変換がらみのことは、p.240〜に記述があります。
引用順変えてます。
> printf() など可変個引数をもつ関数に値を渡すときは
> [signed/unsigned] char/short 型は「暗黙の汎整数変換」によって
> signed int 型に変換されます。
些細な突っ込みですが、汎整数拡張は
6.2.1.1.
| int型が元の型のすべての値を表現できるならば値をintに型変換し、
| それ以外はunsigned int型に型変換する。
という変換ですから、shortとintのサイズが同じ場合にはunsigned shortは
unsigned intに変換されるでしょう。この例では int=16bitとしていますから、
shortとintが同サイズというのもありそうな話に見えます。
> ishikawa さんは難しく考えすぎなのでしょう。
いやあ、もともと結構難しい問題だと思いますよ。
規格書ひっくり返して厳密な解釈を調べるのも勉強になるものですが、
実際にプログラムを書く上では、
・整数型はintを使え。
- はっきりとした理由がなければ、shortもlongもunsignedも使うな。
- 単独の変数としては、charも使うな(たとえ文字コードを格納するのだとしても)。
charは、charへのポインタや、charの配列を使うときだけ使え。
・実数型はdoubleを使え。
- float型の存在は忘れろ。
程度の認識で、さほど困らないように思いますし。
> ・一方のオペランドが型unsigned long intをもつ場合、他方のオペランドを
> unsigned long intに型変換する。
> ・そうでない場合、一方のオペランドが型long intをもち、他方のオペランドが
> 型unsigned intをもち、更に、long intがunsigned intのすべての値を
> 表現できるなら、型unsigned intのオペランドをlong intに型変換する。
> long intがunsigned intのすべての値を表現できないなら、両オペランドを
> unsigned long intに型変換する。
> ・そうでない場合、一方のオペランドが型long intをもつならば、他方の
> オペランドをlong intに型変換する。
> ・そうでない場合、一方のオペランドが型unsigned intをもつならば、
> 他方のオペランドをunsigned intに型変換する。
> ・そうでない場合、両オペランドは型intをもつ。
これってdouble型の場合どうなるんでしょうか?
それと他のとこでも質問したら規格書規格書ってでてくるんですが、規格書って本屋さんに売ってるんですかね?
なんか欲しくなってきました・・。
> 2.暗黙の汎整数変換
> printf() など可変個引数をもつ関数に値を渡すときは
> [signed/unsigned] char/short 型は「暗黙の汎整数変換」によって
> signed int 型に変換されます。
> # 他の型と演算されるときは 494 の規則によって変換されます。
これは可変引数にしか通用しないんですか?
> 3. printf() の %c の動作
> %c で1文字表示する場合でも 2. により必ず int 型を受け取ることになります。
> [signed/unsigned] char c=0xb1;
> printf("%c", c);
> これは暗黙のうちに printf("%c", (int)c); になるのです。
> 規則 2 によって2番目の引数は 0x00b1 または 0xffb1 となります。
> しかし %c は与えられた引数の下位8ビットだけを取り扱うため
> 0x00b1 でも 0xffb1 でも表示は b1 の部分だけ見て行われます。
これってbig-endianだったらffかb1の部分を見て行われるんですね?
(endianって言う単語はここの書き込みででてたので速攻で調べただけです、間違い
だったら申し訳ない)
それと他のところに
>まず little-endian の場合
>スタックには 61 00 00 00 00 00 00 00 41 00 00 00 00 00 00 00 が積まれています。
>最初の %c は vaarg を使って int を取り出そうとします。
>61000000 を取り出し 'a' が表示されます。
>次の %c も同じく int を取り出そうとして
>00000000 を取り出し (おそらく) 空白文字が表示されます。
>'A' は出力されません。
とありますが%cは8ビットを取るんじゃないんですか?