드라이버와 펌웨어는 C++가 아닌 C 또는 ASM으로 작성되는 경우가 많은 이유는 무엇입니까?
드라이버나 펌 웨어는 C++가 아닌 C나 Assembly에 기재되어 있는 것이 왜인지 궁금할 뿐입니다.
여기에는 기술적인 이유가 있다고 들었습니다.
아는 사람 있어요?
많은 사랑, 루이스
많은 경우 c는 컴파일할 때 더 빠르고 더 작고 다른 OS 버전 간에 컴파일이 일관적이며 의존성이 낮기 때문입니다.또한 c++는 실제로 c를 기반으로 구축되어 있기 때문에, 문제는 그것이 제공하는 것이 필요한가 하는 것입니다.
드라이버나 펌 웨어를 쓰는 유저는, 통상, OS 레벨(또는 그 이하)로 작업하는 것에 익숙해져 있기 때문에, 이러한 타입의 문제에 c 를 사용하는 것에 익숙해져 있을 가능성이 있습니다.
대부분의 경우 운영 체제(또는 런타임 라이브러리)는 C++에 필요한 stdlib 기능을 제공하기 때문입니다.
C 및 ASM 에서는, 외부 의존 관계가 없는 베어 실행 파일을 작성할 수 있습니다.
다만, Windows 는 C++ stdlib 를 서포트하고 있기 때문에, 대부분의 Windows 드라이버는 C++ 로 써집니다.
또, 펌 웨어가 ASM 에 기술되어 있는 경우는, 통상, (A) 실행중의 플랫폼에 C++ 컴파일러가 없거나 (B) 속도나 사이즈의 제약이 있기 때문입니다.
(B)는 2000년대 초반 이후 일반적으로 문제가 되지 않았습니다.
커널의 코드는 사용자 공간과는 매우 다른 환경에서 실행됩니다.프로세스를 분리할 수 없기 때문에 오류를 복구하기가 훨씬 어렵습니다. 예외는 거의 불가능합니다.메모리 할당자가 다르기 때문에 취득이 어려울 수 있습니다.new
그리고.delete
커널 컨텍스트에서 올바르게 동작합니다.사용할 수 있는 표준 라이브러리가 적기 때문에 C++와 같은 언어를 효과적으로 사용하는 것이 훨씬 더 어렵습니다.
Windows 에서는, C++ 의 극히 한정된 서브셋을 커널 드라이버에 사용할 수 있습니다.기본적으로, 블록의 선두 이외의 장소에서의 변수 선언 등, C 로의 변환이 가능한 것을 말합니다.그들은 의 사용을 권장하지 않는다.new
그리고.delete
RTI 또는 대부분의 C++ 표준 라이브러리는 지원하지 않습니다.
Mac OS X는 C++의 제한된 서브셋을 기반으로 하는 프레임워크인 I/O 키트를 사용합니다.단, Windows에서 허용되는 것보다 더 완전한 것은 아닙니다.기본적으로 예외 없는 C++와 RTTI입니다.
대부분의 Unix 계열 운영체제(Linux, BSD)는 C로 작성되어 있습니다.커널 내의 C++는 일반적으로 한정되어 있기 때문에 커널에 C++ 지원을 추가하는 것의 이점을 실제로 본 사람은 없다고 생각합니다.
매장에서는 C++와 비교하여 C를 임베디드 시스템에 사용하는 이유에 대해 다음과 같은 코멘트가 있습니다.
- C++는 코드 블러트를 생성합니다.
- C++ 예외는 너무 많은 공간을 차지합니다.
- C++ 다형 및 가상 테이블이 메모리 또는 실행 시간을 너무 많이 사용합니다.
- 가게 사람들은 C++ 언어를 모릅니다.
유일한 타당한 이유는 마지막일 수 있다.OOP, 함수 객체, 가상 기능을 통합한 C 언어 프로그램을 본 적이 있습니다.그것은 매우 빠르게 추해지고 코드를 흐트러뜨린다.
C에서의 예외 처리는 올바르게 구현되면 많은 공간을 차지합니다.나는 C++와 거의 같다고 말할 것이다.C++ 예외의 장점은 언어이므로 프로그래머가 바퀴를 재설계할 필요가 없다는 것입니다.
임베디드 시스템에서 C보다 C++를 선호하는 이유는 C++가 더 강력한 타이핑 언어이기 때문입니다.컴파일 시간 내에 더 많은 문제를 발견할 수 있으므로 개발 시간이 단축됩니다.또한 C++는 C보다 객체 지향 개념을 구현하기 쉬운 언어입니다.
C++에 반대하는 이유의 대부분은 실제 언어보다는 디자인 개념에 관한 것입니다.
툴의 서포트와 하드웨어의 휴대성을 제외하면, C에 한정할 설득력 있는 이유는 없다고 생각합니다.C++에서 보다 자연스럽게 할 수 있는 복잡한 손으로 코딩된 작업을 종종 볼 수 있습니다.
- 같은 데이터 구조(종종 「개체」라고 불린다)에서만 동작하는 함수(비범용)의 「모듈」로 그룹화 -> C++ 클래스를 사용한다.
- 모듈 함수가 데이터 구조의 "인스턴스"와 연동할 수 있도록 "핸들" 포인터를 사용합니다.-> C++ 클래스를 사용합니다.
- 모듈의 API에 포함되지 않은 파일 범위 정적 함수 -> C++ 개인 멤버 함수, 익명 네임스페이스 또는 "상세" 네임스페이스.
- 함수 유사 매크로 사용 -> C++ 템플릿 및 인라인/콘스펙스르 함수 사용
- 수동 vtable("descriptor") 또는 스위치 문과 함께 디스패치된 유형 ID에 따라 실행 시 동작이 달라집니다.-> C++ 다형성
- 통신 포트와의 데이터 마샬링/디마샬링 또는 비포터블 구조 사용에 대한 오류 발생 가능성이 높은 포인터 연산 -> C++ 스트림 개념(반드시 std::iostream은 아님)
- 이름 충돌을 피하기 위해 모든 항목에서 지옥 접두사를 붙입니다.C++ 네임스페이스
- 컴파일 시간 상수로서의 매크로 -> C++11 constexpr 상수
- 핸들이 범위를 벗어나기 전에 리소스를 닫지 않음 -> C++RAIi
위에서 설명한 C++ 기능 중 수기 C 구현보다 비용이 많이 드는 기능은 없습니다.좀 더 놓치고 있는 것 같아요이 지역의 C의 관성은 C가 주로 사용되는 것과 더 관련이 있다고 생각합니다.
물론 제약이 있는 환경에서는 STL을 자유롭게(또는 전혀) 사용할 수 없는 경우도 있지만, 그렇다고 해서 C++를 "더 나은 C"로 사용할 수 없는 것은 아닙니다.
Windows 드라이버는 C++로 기술되어 있습니다.
Linux 드라이버는 커널이 c로 쓰여져 있기 때문에 c로 쓰여집니다.
1) "항상 그래왔기 때문에" - 현재 시스템의 거의 모든 API는 원래 C 또는 ASM 기반 모델에 작성되어 있으며, C 및 ASM에 많은 이전 코드가 존재하기 때문에 C++의 이점을 활용하는 방법을 알아내는 것보다 '흐름에 따르는' 것이 더 쉬운 경우가 많습니다.
2) 환경 - C++의 모든 기능을 사용하려면 상당한 런타임 환경이 필요합니다.그 중 일부는 드라이버에게 제공하기가 귀찮습니다.기능 세트를 제한하면 더 쉽게 할 수 있지만, 특히 메모리 관리는 힙이 많지 않으면 C++에서 매우 흥미로워질 수 있습니다.이 환경에서는 RTI와 마찬가지로 예외를 고려하는 것도 매우 흥미롭습니다.
3) "도대체 뭘 하는지 모르겠어요"어느 합리적으로 숙련된 프로그래머라도 C의 라인을 보고 그 라인을 구현하기 위해 기계 코드레벨에서 무슨 일이 일어나는지 잘 알 수 있습니다.최적화는 분명 어느 정도 변화를 주지만, 대부분의 경우 무슨 일이 일어나고 있는지 알 수 있습니다.C++에서는 연산자 오버로드, 컨스트럭터, 디스트럭터, 예외 등이 주어진 코드 라인에서 어떤 일이 일어날지 알기 어렵습니다.디바이스 드라이버를 쓸 때는, 메모리 매니저와 대화할 것인지, 코드의 행이 인터럽트 레벨이나 마스킹에 영향을 주는 것인지(또는 그에 따라) 알 필요가 있는 경우가 많기 때문에, 이것은 치명적일 수 있습니다.
C++ 를 사용해 Windows 로 디바이스 드라이버를 작성할 수 있습니다.제가 직접 작성했습니다.주의할 점은 사용하는 C++ 기능과 사용처에 주의할 필요가 있다는 것입니다.
C++가 아닌 C가 사용되는 이유는 다음과 같습니다.
- C++가 느리니까
- 또는 c-runtime이 이미 존재하기 때문입니다.
C++는 예외를 사용하기 때문입니다.드라이버는 OS가 하드웨어 인터럽트에 응답할 때 호출되기 때문에 C++ 언어 예외 구현의 대부분은 드라이버 코드에서 사용할 수 없습니다.하드웨어 인터럽트 중에는 재귀 인터럽트를 일으킬 수 있으므로 드라이버 코드는 예외를 사용할 수 없습니다.또한 인터럽트 컨텍스트에서 코드화할 수 있는 스택공간은 일반적으로 매우 작습니다(또한 예외 없음 규칙의 결과로 확장할 수 없습니다).
물론 new(std::nothrow)를 사용할 수 있지만, 현재 c++의 예외는 biiquitious이기 때문에 std::nothrow 시멘틱스를 사용하는 라이브러리 코드에 의존할 수 없습니다.
또, C++가 C:- 의 몇개의 기능을 포기했기 때문에, 드라이버에서는 코드 배치가 중요합니다.디바이스 드라이버는 인터럽트에 응답할 수 있어야 합니다.인터럽트 코드는 "페이지되지 않은" 코드 세그먼트에 배치하거나 메모리에 영구적으로 매핑해야 합니다. 즉, 코드가 페이지 메모리에 있는 것처럼 호출될 때 호출될 수 있으므로 예외가 발생할 수 있으며, 이는 금지됩니다.드라이버 개발에 사용되는 C 컴파일러에는 #pragma 명령어가 있으며, 어떤 유형의 메모리 함수가 최종적으로 사용되는지를 제어할 수 있습니다.페이징되지 않은 풀은 매우 제한된 리소스이므로 드라이버 전체를 페이징되지 않은 것으로 표시하지 마십시오.그러나 C++는 많은 암묵적 코드를 생성합니다.예를 들어 기본 생성자입니다.암묵적으로 생성된 C++ 코드를 괄호로 묶어서 그 배치를 제어할 수 있는 방법은 없으며 변환 연산자가 자동으로 호출되므로 코드 감사가 호출된 코드에 대한 부작용이 없음을 보장할 수 없습니다.
요약하면:- 드라이버 개발에 C++가 아닌 C가 사용되는 이유는 C++로 작성된 드라이버가 과도한 양의 비페이징 메모리를 소비하거나 OS 커널을 크래시하기 때문입니다.
초경호 자바 대신 C를 사용하는 가장 큰 이유는 어떤 메모리가 특정 작업에 사용되는지 쉽게 파악할 수 있기 때문입니다.C는 매우 주소 지향적입니다.커널 코드를 쓸 때 중요한 것은 불편한 순간에 페이지 장애를 일으킬 수 있는 메모리 참조를 피하는 것입니다.
C++를 사용할 수 있지만 가상 함수를 호출할 때 vtable을 사용하여 런타임 머신을 암묵적으로 호출할 때 고정 메모리(페이지 불가능)의 내부 테이블만 참조하도록 런타임에 특별히 조정된 경우에만 사용할 수 있습니다.이 특별한 적응은 대부분의 경우 "즉석에서" 나오지 않습니다.
C를 플랫폼에 통합하는 것은 C를 표준 라이브러리에서 분리하여 메모리 액세스를 완전히 명시적으로 제어할 수 있기 때문에 훨씬 더 쉽습니다.이 언어는 잘 알려진 언어이기도 하지만 커널 툴 설계자가 선택하는 경우가 많습니다.
편집: 신규 콜 및 삭제 콜에 대한 참조가 삭제되었습니다(잘못/오해). 보다 일반적인 "런타임 머신" 문구로 대체되었습니다.
C는 기계에 의존하지 않는 어셈블리 언어에 매우 가깝습니다.대부분의 OS형 프로그래밍은 '베어메탈' 수준으로 다운되어 있습니다.C에서는, 판독한 코드가 실제의 코드입니다.C++는 C가 숨길 수 없는 것을 숨길 수 있습니다.
이것은 제 의견일 뿐입니다만, 저는 지금까지 디바이스 드라이버나 OS 관련의 디버깅에 많은 시간을 소비해 왔습니다.어셈블리의 언어를 보고 있는 경우가 많습니다.낮은 레벨로 심플하게 해, 애플리케이션 레벨의 고급화를 도모합니다.
드라이버와 펌웨어가 대부분 C 또는 ASM으로 작성되는 이유는 실제 런타임 라이브러리에 의존하지 않기 때문입니다.여기 C로 쓰여진 상상 속의 운전자를 상상해 보세요.
#disc <Stadio.h> # OS 정의_VER 5.10#드라이버의 정의_VER "1.2.3" int drivermain(드라이버 구조 정보 **dsi){if ( ( * dsi ) - > version > OS _ VER ) {(*dsi)->InitDriver();printf("FooBar 드라이버가 로드되었습니다\n"); printf("버전: %s", DRIVER_VER); (*dsi)-> 디스패치 = foo Dispatch;}카운트 { }(*dsi)-> 종료(0); }} void foo Dispatch(드라이버 구조 정보 *dsi){printf("Dispatched %d\n", dsi-> GetDispatchId()); }
런타임 라이브러리의 서포트는 컴파일/링크시에 도입 및 링크 할 필요가 있습니다.런타임 환경(즉, operating system이 로드/초기화 국면에 있는 경우)이 완전하게 설정되어 있지 않기 때문에, 그 방법에 대한 힌트가 없습니다.printf
operating system(Linux의 경우 커널 패닉, Windows의 경우 블루스크린의 경우)의 실행 방법에 대한 참조가 없기 때문에, operating system의 종말음이 울릴 가능성이 있습니다.
즉, 드라이버 코드는 같은 공간을 공유하는 커널 코드와 함께 코드를 실행할 수 있는 특권을 가집니다.ring0은 궁극의 코드 실행 특권(모든 명령 허용), ring3은 운영 체제의 프런트 엔드가 실행되는 곳(제한된 실행 특권), 즉 ring3 코드는 실행할 수 없습니다.명령어는 ring0용으로 예약되어 있습니다.커널은 마치 "Hey, you are not privilege to dump up ring0's domain"이라고 말하는 것처럼 트랩함으로써 코드를 삭제합니다.
어셈블러에 기술되어 있는 또 다른 이유는 주로 코드 사이즈와 원시 속도입니다.예를 들어 시리얼 포트 드라이버의 경우 타이밍, 레이텐시, 버퍼링과 관련하여 함수에 대해 입출력이 '중요'합니다.
(윈도의 경우) 대부분의 디바이스 드라이버는 C 코드를 사용할 수 있지만 일반 표준 C의 런타임 라이브러리에는 링크가 없는 특별한 컴파일러 툴 체인(WinDDK)을 가지고 있습니다.
Visual Studio, VisualDDK 내에서 드라이버를 빌드할 수 있는 툴킷이 1개 있습니다.드라이버를 빌드하는 것은, 확실히, 블루 스크린, 커널 패닉, 그리고 왜 그럴까, 드라이버의 디버깅등을 응시하는 것으로써, 스트레스 유발의 액티비티를 얻을 수 있습니다.
디버깅 쪽은 더 어렵고, 링0 코드는 문이 닫혀 있기 때문에 링3 코드로 쉽게 액세스 할 수 없습니다.커널 트랩 도어를 통해 (더 좋은 단어가 필요하기 때문에) 정중하게 요청하면 커널이 링0에 상주하는 핸들러에게 태스크를 위임하는 동안 문은 닫힌 상태로 유지됩니다.어떤 결과가 반환되든 실행은 반환됩니다.3 코드를 호출해도 문은 굳게 닫힌 상태로 유지됩니다.이것이 사용자랜드 코드가 ring0에서 특권 코드를 실행하는 방법의 유사 개념입니다.
Furthermore, this privileged code, can easily trample over the kernel's memory space and corrupt something hence the kernel panic/bluescreens...
Hope this helps.
Perhaps because a driver doesn't require object oriented features, while the fact that C still has somewhat more mature compilers would make a difference.
There are many style of programming such as procedural, functional, object oriented etc. Object oriented programming is more suited for modeling real world.
I would use object-oriented for device drivers if it suites it. But, most of the time when you programming device drivers, you would not need the advantages provided by c++ such as, abstraction, polymorphism, code reuse etc.
Well, IOKit drivers for MacOSX are written in C++ subset (no exceptions, templates, multiple inheritance). And there is even a possibility to write linux kernel modules in haskell.)
Otherwise, C, being a portable assembly language, perfectly catches the von Neumann architecture and computation model, allowing for direct control over all it's peculiarities and drawbacks (such as the "von Neumann bottleneck"). C does exactly what it was designed for and catches it's target abstraction model completely and flawlessly (well except for implicit assumption in single control flow which could have been generalized to cover the reality of hardware threads) and this is why i think it is a beautiful language.) Restricting the expressive power of the language to such basics eliminates most of the unpredictable transformation details when different computational models are being applied to this de-facto standard. In other words, C makes you stick to basics and allows pretty much direct control over what you are doing, for example when modeling behavior commonality with virtual functions you control exactly how the function pointer tables get stored and used when comparing to C++'s implicit vtbl allocation and management. This is in fact helpful when considering caches.
Having said that, object-based paradigm is very useful for representing physical objects and their dependencies. Adding inheritance we get object-oriented paradigm which in turn is very useful to represent physical objects' structure and behavior hierarchy. Nothing stops anyone from using it and expressing it in C again allowing full control over exactly how your objects will be created, stored, destroyed and copied. In fact that is the approach taken in linux device model. They got "objects" to represent devices, object implementation hierarchy to model power management dependancies and hacked-up inheritance functionality to represent device families, all done in C.
because from system level, drivers need to control every bits of every bytes of the memory, other higher language cannot do that, or cannot do that natively, only C/Asm achieve~
ReferenceURL : https://stackoverflow.com/questions/2039444/why-are-drivers-and-firmwares-almost-always-written-in-c-or-asm-and-not-c
'programing' 카테고리의 다른 글
페이지를 새로 고칠 때마다 계속 계산하는 방법 (0) | 2022.06.01 |
---|---|
[ Dynamic access object ]필드 (0) | 2022.06.01 |
정적 콘텐츠(예: 국가 코드)를 vue.js 앱의 어디에 저장합니까? (0) | 2022.06.01 |
Vue.js에서 컴포넌트가 재렌더되는 원인이 되는 데이터 변경을 찾는 방법 (0) | 2022.06.01 |
Vue : 텍스트 영역 입력의 문자를 제한하시겠습니까?필터를 잘라내시겠습니까? (0) | 2022.06.01 |