質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

4155閲覧

OS開発にC++を使いたい。

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2018/08/04 05:53

編集2018/08/04 07:31

C++が非常に優れた言語だという事が徐々にわかってきたので、OS制作にC++を採用したいと考えています。

しかし!!問題があります。
STLが使えない!
当たり前です。システムコールがない環境でシステムコールを使用しようとしているようなものです。

そこで、STLをfree standing環境でも使えるようにする必要があります。
しかし!ここにもまた問題が出現します。

Linuxを元にして制作することを考えましょう。
全て1人で作るのは無理なので!

new や vector、STLは、間違いなく動的記憶期間を利用しています。
前回の質問の通りです。
C++ヒープ領域について

このnewの部分をLinuxカーネルが採用しているスラブアローケータなどの確保関数に書き換えれば、行ける!!と考えました。

ここからが問題です。!!
(kmalloc や vmallocはここへどうぞ!)

malloc関数は、PODでない場合は使ってはマズイはずです。
In what cases do I use malloc vs new?
これと同じように、トリビアルでないクラスの場合に、vmallocやkmallocが安全に使えるか?
という疑問が出てきます。
これは、もしかしてダメな可能性がある!
そうなると・・・スラブアローケータをC++で独自に作り直さなくてはならなくなります。


あ、ちなみに・・・トリビアルなクラスについて確認です。
trivial classこちらを参考にしました。

ユーザー定義のコンストラクタ、コピーコンストラクタ

ムーブコンストラクタ、コピー代入演算子、ムーブ代入演算子、デストラクタを定義していない

trivially copyable class

これはユーザー定義したコピーコンストラクタ、ムーブコンストラクタ、コピー代入演算子、ムーブ代入演算子、デストラクタがないクラス。つまりコンストラクタだけはユーザ定義可能で、その他の自動生成される関数はコンパイラ定義なクラスということ。

コピー可能なトリビアルは、C言語と互換性ありましたっけ??(PODでしたっけ?)
コンストラクタ、デストラクタが使えないと・・・不便でしょうがないですね。

struct test{ test(int a){}; }

これって、引数ありのコンストラクタを定義しています。
この場合、コンパイラ定義のデフォルトコンストラクタって付いてくるんでしたっけ?
コンパイラ定義のデフォルトコンストラクタがあるなら、これはトリビアルなクラスでしょうか??
それとも、ユーザー定義が1でもあれば、それはもうトリビアルなクラスで無くなってしまうんですか?

この辺りイマイチちゃんと理解できてないです。


もう1つ問題があります。
速度についてです。
Linuxカーネルは、速度向上のため、memcpy関数などもC言語ではなく、アセンブリ言語で実装しています。

static void *__memcpy(void *dest, const void *src, size_t n) { long d0, d1, d2; asm volatile( "rep ; movsq\n\t" "movq %4,%%rcx\n\t" "rep ; movsb\n\t" : "=&c" (d0), "=&D" (d1), "=&S" (d2) : "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src) : "memory"); return dest; }

この関数・・・トリビアルでないクラスで使うとマズイ??

前回の質問で、yumetodoさんが上げているコード、uninitialized_move_if_noexcept_or_copy()をアセンブリ言語レベルで人為的に最適化を施さないと、Linux kernelレベルの速度を出せいないのでは??
ということですね。

つまり、既存のコードとの互換性の部分で問題が生じる・・・ということです。
これは、どうすれば良いと思いますか??
コンストラクタ、デストラクタを全面的に使用しないで、速度、互換性を優先するか?
それとも、積極的にコンストラクタとデストラクタを使用していく方針が良いか?

前者だと・・・C++を使う必要性が薄れてしまいますね。
逆に、後者だと、既存のコードをほぼ書き換えなくてはならなくなる可能性が・・・

どちらもちょっと・・・うーーん微妙ですね。

どちらが良い方法だと思いますか?
それか他になにか良い方法はありませんか?
OSは、速度が重要なので、C++で作ってカクカク動かれると困るんですよね。

こちらも参考にしました。こんなに制約がつくと流石にマズイですね。
Plain Old Data

それほど間違っていないPOD型

・自分でコンストラクタとか定義してない ・virtualという文字列を打ってない ・継承してない ・メンバ変数はprivate(もしくはpublic)にしか定義してない ・組み込み型(int, char, float…etc)しかメンバに持ってない

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2018/08/04 06:38 編集

質問がでかすぎる・・・。最長不倒関数ならぬ最長不倒質問か?
strike1217

2018/08/04 07:14

そうでしょうか。うーん。どう減らしましょう。
strike1217

2018/08/04 07:29

少し修正します。速度の部分については、volatileが絡んでくるので無視してもらっても構いません。
cateye

2018/08/04 10:17 編集

話が大きすぎるようです、現在のLinux(2015年8月:v4.2)は約 20,000,000行ほどあるそうです。で、どの程度のOSをお考えでしょう?
strike1217

2018/08/04 10:31

分かりにくくてすいません。OSの規模はどうでも良いのです。STLを使う際の問題をどう解決するか?ということです。
cateye

2018/08/04 10:56 編集

OSあるいはアプリでもそうですが、仕様が決まらない状態で言語を選ぶのは本末転倒だと思います。まず、作りたいOSやアプリの仕様や規模を考えた上でハード、言語を選びましょうd^^・・・手段を目的にしないように・・・
strike1217

2018/08/04 10:58

そういう手順なんですか!最初からC++!っていう風に決めていたもので!
cateye

2018/08/04 11:07

まぁ、客先からの依頼(〜言語で開発とか)とか言うなら分からんでもないですが、その時はすでに仕様は決まっているいるはずから。
guest

回答4

0

ベストアンサー

こんにちは。

このnewの部分をLinuxカーネルが採用しているスラブアローケータなどの確保関数に書き換えれば、行ける!!と考えました。

ここからが問題です。!!
(kmalloc や vmallocはここへどうぞ!)
malloc関数は、PODでない場合は使ってはマズイはずです。

この流れは謎です。
newはメモリ確保とコンストラクタ呼び出し、deleteはデストラクタ呼び出しとメモリ解放を行います。このメモリ確保/開放処理にmallocだろうがkmallocだろうが仕様を満たすものを使う分には、そのクラスがPODとかそうでないとかは無関係です。

PODやtrivial云々はオブジェクトをコピーする際に、コピー演算子やコピー・コンストラクタを使わなくても良いかどうかの概念の筈です。(trivialは複雑すぎてきちんとは理解していませんが。)
オブジェクトをコピーやムーブする際には、通常のコピー演算子等を使えばよいです。

OS開発の際には、コピー演算子等を呼び出せないけどコピーしたいケースがあるかも知れません。(例えばDMAでコピーしたい時とか?)
そのようなクラスに限って、trivial copyableのようなクラスになるよう注意深く記述すればよいはずです。

コンストラクタ、デストラクタを全面的に使用しないで、速度、互換性を優先するか?

それとも、積極的にコンストラクタとデストラクタを使用していく方針が良いか?
前者だと・・・C++を使う必要性が薄れてしまいますね。

全くその通りと私も思います。アセンブラ・コードを見ながら最適化する程速度を追求するならC言語の方が手間は省けるだろうと思います。

逆に、後者だと、既存のコードをほぼ書き換えなくてはならなくなる可能性が・・・

この「既存のコード」ってなんでしょうか?
linuxのカーネル? それともlinux上にある多数のアプリ?
どちらにしても、C++はC言語とのインタフェースもサポートしますから、既存のコードがC言語で記述されている場合、その部分とのインタフェースの互換性を維持することは理論上可能な筈です。

投稿2018/08/04 10:10

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2018/08/04 10:36

あーそうそう、こういうことが言いたかった。徹夜明けでビシッと言う能力が消えていた
strike1217

2018/08/04 10:38

単純に自分の理解不足です。 クラスに関する理解が不足していました。 > 「既存のコード」とは、Linux kernelのことです。 > PODやtrivial云々はオブジェクトをコピーする際に、コピー演算子やコピー・コンストラクタを使わなくても良いかどうかの概念の筈です。 え!あ!そうなんですか!C言語と完全に互換性があるバイト列のことだと考えていたので、mallocなどは、このPODやトリビアルなクラスでないと使えないのかと勘違いしていました。 mallocは単にコンストラクタやデストラクタは呼ばれないだけですね。
strike1217

2018/08/04 10:43

>OS開発の際には、コピー演算子等を呼び出せないけどコピーしたいケースがあるかも知れません。 そのようなクラスに限って、trivial copyableのようなクラスになるよう注意深く記述すればよいはずです。 ほぉ!なるほど!
guest

0

まー、いろんなワケワカメな用語を振り回しておられますが、いろいろやってみればいいとは思います。
やってるうちに、こんなはずじゃなかった、というのが頻出すると思いますので、できるだけ早い段階で路線変更なさることを祈っております。
#OS開発、というものにC++はねえ、まあ、なんというか、がんばってくださいw

まあ、お察しの通り、まずはメモリ管理ユニットの実装から始めましょうねっ。

投稿2018/08/04 08:50

編集2018/08/04 08:52
y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

このnewの部分をLinuxカーネルが採用しているスラブアローケータなどの確保関数に書き換えれば、行ける!!と考えました。

アロケーターというのがあってすね・・・

malloc関数は、PODでない場合は使ってはマズイはずです。

違います。単に未初期化な領域になるだけなので、配置newすればいいだけです。ただしアライメントは気をつけましょう。

コピー可能なトリビアルは、C言語と互換性ありましたっけ??(PODでしたっけ?)

PODという概念は滅びましたので忘れてください。trivially copyable classならmemcpyで扱っても安全です。(かつて存在したPODという概念は考古学的にはtrivially copyable classかつstanderd layoutなクラスを指していた。)

この場合、コンパイラ定義のデフォルトコンストラクタって付いてくるんでしたっけ?

YES.

特殊メンバ関数とコンパイラによる暗黙宣言 - yohhoyの日記

コンパイラ定義のデフォルトコンストラクタがあるなら、これはトリビアルでしょうか??
それとも、ユーザー定義が1でもあれば、それはもうトリビアルで無くなってしまうんですか?
おまけに、仮想関数までダメみたいですね。
仮想関数を持ってたら、トリビアルじゃ無くっちゃいます?
これともコピー可能なトリビアルじゃ無くなっちゃいます??

単にtrivialというだけでは何がtrivialかわからないので、お話になりません。

前回の質問で、yumetodoさんが上げているコード、uninitialized_move_if_noexcept_or_copy()をアセンブリ言語レベルで人為的に最適化を施さないと、Linux kernelレベルの速度を出せいないのでは??

ということですね。

アセンブリで書けばコンパイラの最適化に勝てるという夢を見続けたいならばご自由に。

コンストラクタ、デストラクタを全面的に使用しないで、速度、互換性を優先するか?

コンパイラの最適化をなめ過ぎでは?最適化なんて-O2つけとけば概ね十分です。あなたが考えつく程度の差は最適化だけで吹き飛びます。

OSは、速度が重要なので、C++で作ってカクカク動かれると困るんですよね。

動かないより遅いほうがいいに決まってます。

それほど間違っていないPOD型

だからPODというのは考古学の分野ですってば!

投稿2018/08/04 06:23

編集2018/08/04 06:32
yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2018/08/04 07:05

> 単に未初期化な領域になるだけ あ、そうなんですか! では、malloは普通にトリビアルなクラスじゃなくても使用可能なんですね! > PODという概念は滅びましたので忘れてください。 trivially copyable classならmemcpyで扱っても安全です。 え?そうなんですか? なんか変ですね。ちょっと待ってください。
strike1217

2018/08/04 07:10

ああ!そうか!間違えました。 そうですね。 「trivially copyable classならmemcpyで扱っても安全です。」 その通りですね。
strike1217

2018/08/04 11:01

ユーザー定義が1でもあれば、トリビアルなクラスでは無いんですか?
strike1217

2018/08/04 11:09

そうなんですか! んーー。用語がどんでもなく分かりにくいですね。
guest

0

OSに関して詳しい方に聞いてきました。

newの確保関数をスラブアローケータで置き換えた独自の改造版newを作れば、この問題はクリアできそうです。
これなら、トリビアルなクラスであろうとなかろうと安全に使用できるようです。

vmalloc, kmallocを直に使うのはやはりダメでした。
フラグやメモリ領域の連続性、不連続性をパラメータとして渡せるように工夫する必要はありそうです。

newができれば、STLはLinux kernel用に移植できそうです。

投稿2018/08/04 08:57

編集2018/08/04 08:58
strike1217

総合スコア651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2018/08/04 10:42

> vmalloc, kmallocを直に使うのはやはりダメでした。 ダメというより、newのようにコンストラクタやデストラクタは呼び出せない・・・ というだけの話です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問