25 ms·
Moving the Linux Kernel to Modern C
- LAC-Tech 5y agoThey're discussing the move to C99. Not sure that counts as modern C at this point.
- flyingfences 5y agoThey're discussing a move to C11, which counts in my book.
- LAC-Tech 5y agoyeah fair enough should've read the rest of the article before my snide comment
- tombert 5y agoI haven't touched C in any serious capacity in quite awhile; how often does C get new revisions, because isn't C11 still more than a decade old? I understand why the linux kernel folks aren't moving to the bleeding edge (Linux is old, you have to do these ports incrementally), but I'm curious why the pace of language is so slow. I guess it's because C has more or less stabilized and thus further revisions are less necessary?
- LukeShu 5y ago> how often does C get new revisions 1989, 1995, 1999, 2011, 2017. The 1995 one was an "amendment", not a full revision (and is mostly additions to libc, which Linux doesn't get to use; the only language change is the addition of digraphs). C17 was a "bugfix" revision; compilers will have applied these fixes to their C11 implementations, so in effect the only difference between C11 and C17 is the value of __STDC_VERSION__. So for most intents and purposes C11 is still the most recent revision.
- dahfizz 5y ago> but I'm curious why the pace of language is so slow. I guess it's because C has more or less stabilized and thus further revisions are less necessary? That is a big part of it. C is an old, stable, complete language. There is also the existence of gnu extensions, which bridge the gap between language revisions. For example, anonymous unions were added in C11 but they have been a gnu extension since forever.
- syncsynchalt 5y ago> I'm curious why the pace of language is so slow This is a strength of the language. If you've ever done CI/CD for a large project in a fluid development ecosystem (e.g. nodeJS), you can understand why it might be refreshing to develop your operating system in a language where standards are measured by the decade.
- clhodapp 5y agoGiven that C99 is much closer in vintage to their current C89 than it is to today's date and also just straight up really old, it does seem inappropriate to distinguish that as "modern C". That said they do seem to be discussing both C99 and C11 so it does seem like going with something that would qualify as modern (especially in light of Linux's need to be conservative) is actually on the table.
- dahfizz 5y agoYou also have to look at the contents of the revisions. C99 was a massive update for C, and C11 was tiny in comparison (and C17 was basically nothing at all). Writing C89, without variable declaration in a for loop, and without // comments, etc, feels ancient. C99 on the other hand is what defines how C looks today. This is also why the attitude is: if they jump to c99, they may as well jump to c11 because they are basically the same.
- eatbitseveryday 5y ago> if all goes well, the shift to C11 will happen in the next kernel release
- stjohnswarts 5y agoI'll be pinning that for a couple releases unless there's a major security bug O_O
- yjftsjthsd-h 5y agoJust stick to a LTS branch; no reason to give up bugfixes.
- kwijibob 5y agoDoes C standard naming have a Y2K problem? :)
- teddyh 5y agoNot until 2089.
- qiskit 5y agoThe C standards aren't published at a regular interval of 10 years. They are published as needed or as agreed upon. So it is possible there may be a C standard published in 2089, but highly unlikely. It's similar to but not quite the same thing as the Y2K problem.
- jacobr1 5y agoSo it is like a hashtable collision
- syncsynchalt 5y agoGiven C's ubiquity and (likely) longevity it'll have a Y2k89 problem: standards released in 2089 and beyond will have to change their naming schema and/or avoid being standardized in particular years. ;)
- marcosdumay 5y ago> or avoid being standardized in particular years. That's a very "legacy code" way of avoiding the problem, it's just a great option for a centenary frozen language. "Oh, no, look, C98 is from 2198. Do not confuse it with C97 that was settled in 2097."
- dale_glass 5y agoOne thing I've wondered for some time is why don't the Linux developers modify the compiler to suit their needs better. At that project scale, wouldn't it start making sense to start solving problems like "If it were possible to write a list-traversal macro that could declare its own iterator [...]" by adding the functionality you want to GCC?
- deleted 5y ago[deleted]
- na85 5y agoI'm not a compiler expert here but when clang was new and one of the BSD distros was making a lot of hay about moving to it, I remember one of the arguments in favor being that the GCC codebase is a mess and not easily extended.
- Jtsummers 5y agoThat would make the code (and the compiler) non-C89 compliant. At which point, why not move to a different standard rather than bork both the kernel and the compiler if it can meet the needs better?
- electroly 5y agoThe Linux kernel requires GNU extensions; it's already not ANSI C89.
- deleted 5y ago[deleted]
- Jtsummers 5y agoAlright, making it more non-compliant, then. Still creates problems for everyone and also necessitates a larger jump in the GCC version to support (unless you're going to back port the new extensions to every version that the kernel currently works with). Currently you can compile the Linux kernel with GCC 5.1. If you changed the compiler to support this one feature (or any other) you'd either need to back port it several versions (potentially back to 5) or abandon all of them. Which is probably a no-go with a project that's overall as conservative as the Linux kernel project.
- pjmlp 5y agoThe reference to moving into C99 is kind of interesting, given the security work paid by Google to remove all uses of VLAs, I thought they were already using it anyway.
- userbinator 5y agoI'm one of those people who think OS kernels should stay as portable and simple as possible (i.e. C89 or some other easily-bootstrappable language, to avoid Ken Thompson attacks), so this isn't great news to see "the ladder being pulled up another rung". Then again, Linux has already become immensely complex.
- mlindner 5y agoYou're confusing portability with age. Just because something is old does not make it more portable. It arguably makes it less portable as new platforms will not support old language versions.
- thestoicattack 5y agoThe article does mention at least one advantage, so it's not as if the ladder is being pulled up for no reason.
- pm215 5y agoLinux has always relied heavily on GCC extensions, though -- it makes no attempt to actually be C89-compliant portable code. What it actually has is a minimum supported gcc version, which in turn governs whether particular features can be used. In this case the minimum gcc version has for other reasons finally got big enough that C99 and C11 support is definitely present -- the ladder was already this high. (You can also build with clang, but only because clang deliberately aims to support most gcc extensions.)
- Dylan16807 5y agoDeclaring a variable in the middle of a function takes basically no effort to support. Especially compared to all the ridiculous things the kernel gets up to. The ladder's being moved a millimeter.
- mwint 5y agoWhat's a Ken Thompson attack?
- Jtsummers 5y ago
- baby 5y agoI find it scary that most modern infrastructure eventually relies on C, and C from decades ago at that.
- lazide 5y agoYou shouldn’t - it isn’t perfect, but it is well understood. So far we don’t have anything else that works better and all the edge cases and weirdness is understood by enough people that someone could build something like Linux on. It is unwise to build a bridge on something untested with unknown failure modes, and it is equally unwise to do a rewrite or create new core infrastructure in a language without knowing it as well as a civil engineer knows concrete.
- freedomben 5y agoThe amount of fear I see from people around C is so surprising to me. Not saying you fit into this, but so far my anecdata suggests that it's largely people who don't know (or know very little) C. Especially among CS grads whose main exposure to C was in the stack smashing exercise in a security class, all they know about C is the part that was intentionally made vulnerable so it would be easy to exploit. Unless you're being wildly negligent and reckless with your programming, C is really not that scary.
- baby 5y agoMy fear comes from the fact that I was a security consultant, and reviewed a lot of C applications containing nasty bugs.
- kwertyoowiyop 5y agoDefinitely. Though Linux code has probably been tested more thoroughly, and run through more static analysis, than any other C code base. That does help me sleep a little better at night.
- freedomben 5y agoInteresting, I had the same job in mid to late 00s, although I wasn't a consultant so my sample was the company's codebases (of which there were a lot because we built a lot of embedded systems on top of vxworks that did a lot of network communications, sometimes in very niche protocols), not necessarily the codebases of company's that are worried enough that they hire a consultant. That was right around the time when compilers and security tools were becoming available that could flag nearly every possible problem. At that point false positives became a big challenge. What years were you a consultant reviewing C applications?
- charcircuit 5y ago>Raising the minimum GCC version to 8.x would likely be more of a jump than the user community would be willing to accept at this point. If you are using a 0 day old kernel. Why would you be using GCC 5.x still. 5 1 is almost 7 years old now. 8.1 is almost 4. Can't people just use apt / yum / rpm / whatever to upgrade to the latest gcc? Is that really too much to ask of the community?
- lazide 5y agoFor an unstable branch maybe, but if people need to actually use this for real work they will want it compiling on something as well understood and baked as possible - while not being completely obsolete.
- charcircuit 5y agoPeople doing real work are using a kernel compiled with a more up to date GCC. From what I can tell online even RHEL is up to date enough by compiling its kernel with GCC 8.x.
- jahlove 5y agoRHEL7 is still supported [0] by Red Hat through 2026, and is on GCC 4.8.5 [1] [0] https://access.redhat.com/product-life-cycles/?product=Red%20Hat%20Enterprise%20Linux,OpenShift%20Container%20Platform%204 https://access.redhat.com/product-life-cycles/?product=Red%2... [1] https://distrowatch.com/table.php?distribution=redhat https://distrowatch.com/table.php?distribution=redhat
- charcircuit 5y agoCorrect me if I'm wrong but doesn't RHEL stick to a single kernel version and then backport patches?
- yjftsjthsd-h 5y agoOfficially yes, although we can argue about how much you can "backport" and still count. But even so - if new code requires a newer C version and thus newer compiler, it's harder to backport.
- progbits 5y agoFrom [1]: > You are not "introducing" a new macro for this, you are modifying the existing one such that all users of it now have the select_nospec() call in it. > Is that intentional? This is going to hit a _lot_ of existing entries that probably do not need it at all. > Why not just create list_for_each_entry_nospec()? Let's ignore whether this patch is needed or works for now - I don't feel competent to comment on that. But this is such a bad suggestion. Instead of fixing the default to be safe, and possibly having a _unsafe_but_fast() variant for the places where it makes sense they want to keep the broken version and require user to explicitly opt in into safety. Same as the infamous PHP mysql_real_escape_string (don't make the mistake of using mysql_escape_string!) [2][3] or whole host of C stdlib footguns like strcpy/strncpy [4]. The default, easy, obvious option should be safe. The unsafe but faster option should be hard to use by accident and obviously marked as such from the name. [1] https://lwn.net/ml/linux-kernel/Yg6iCS0XZB6EtMP7@kroah.com/ https://lwn.net/ml/linux-kernel/Yg6iCS0XZB6EtMP7@kroah.com/ [2] https://www.php.net/manual/en/function.mysql-escape-string.php https://www.php.net/manual/en/function.mysql-escape-string.p... [3] https://www.php.net/manual/en/function.mysql-real-escape-string.php https://www.php.net/manual/en/function.mysql-real-escape-str... [4] https://en.cppreference.com/w/cpp/header/cstring https://en.cppreference.com/w/cpp/header/cstring
- masklinn 5y ago> Same as the infamous PHP mysql_real_escape_string (don't make the mistake of using mysql_escape_string!) [2][3] TBF that is really a straight bridge to the mysql C API, which is why it’s also in mysqli. MySQL actually has a third one called mysql_real_escape_string_quote, because if the sql mode NO_BACKSLASH_ESCAPES is set the escaping function needs to know what context it’s used in, and thus what quote to double up, and mysql_real_escape_string will fail.
- account42 5y agoAnd of course, the real answer to wether you're supposed to use mysql_escape_string, mysql_real_escape_string or mysql_real_escape_string_quote is "why the fuck are you pasting queries together using string processing".
- deleted 5y ago
- deleted 5y ago[deleted]
- kazinator 5y agoC99 has one nice feature compared to C89 that is little talked about: you can initialize local aggregates using expressions that can't be calculated at load-time. void fun(int x) { struct foo = { x }; // not allowed in C89 int bar[3] = { 0, x }; // ditto } Chances are the kernel does this because, I think, it's also a GNU89 extension.
- marcan_42 5y agoLinux already uses a lot of C99 features that were GNU extensions before C99, like designated initializers. So in practice, Linux is already C99, and hasn't been buildable on strict C89 compilers in a long time.
- quelsolaar 5y agoIn may ways you cant avoid more modern C because more modern standards make thing that were ambiguous more clear, and then compilers follow that even if you select an older standard. I think C99 introduces some bad things that should be keep out of any code base. Variable length arrays being the biggest one. Generics is another one. Being able declare variables anywhere doesn't make the code better but it makes styles diverge and that's a problem. If Linux wants to adopt C99 they should define what parts of c99 should be adopted in their style guide.
- JoshTriplett 5y ago> Variable length arrays being the biggest one. The kernel already used VLAs as an extension, and is currently in the process of removing them from all the code using them.
- pjmlp 5y agoSomeone did a big mistake since 2018 then, https://www.phoronix.com/scan.php?page=news_item&px=Linux-Kills-The-VLA https://www.phoronix.com/scan.php?page=news_item&px=Linux-Ki...
- JoshTriplett 5y agoCorrection: I was mixing up VLAs (which were used before then, and removed) and zero-length/one-element arrays (https://www.kernel.org/doc/html/v5.10/process/deprecated.html#zero-length-and-one-element-arrays https://www.kernel.org/doc/html/v5.10/process/deprecated.htm...).
- nybble41 5y ago> Being able declare variables anywhere doesn't make the code better… It does, though. The ability to declare variables "anywhere" and allows a reduction in the portion of the code where a variable exists uninitialized, or initialized with a dummy value which should never be used, or holding an obsolete value which is not intended to be used. It also allows more variables to be declared `const` (which requires them to be initialized in the declaration, which must occur after the initial value is computed) which helps to detect accidental assignment and also makes the code easier to review. It's worth noting that you can more-or-less declare variables "anywhere" in C89 too—you just have to wrap the variable's scope in a compound statement. From that point of view, C99 doesn't change where variables can be declared. It just lets you remove some syntactic clutter.
- wiineeth 5y agoWhy modern C when you can move to Rust
- yjftsjthsd-h 5y agoBecause we want a kernel that works today, and make improvements that can ship this year, not spend a decade rewriting working software.
- Koshkin 5y agohttps://thenewstack.io/rust-in-the-linux-kernel-good-enough/ https://thenewstack.io/rust-in-the-linux-kernel-good-enough/ > the objective was not to rewrite the kernel’s 25 million lines of code in Rust, but rather to augment new developments with the more memory-safe language than the standard C normally used in Linux development.
- johnisgood 5y agoWhen are you going to start? Contributions are welcome.
- thetic 5y agoThough C89 does not support declaration of a scoped loop variable like C99 does: for(int i = 0; i < 10; i++) { // ... } C89 does support declaration of variables at the top of braced blocks whose scope is limited to that block: { int i; for(i = 0; i < 10; i++) { // ... } }
- spc476 5y agoThen you get dinged by static analysis tools like SonarQube because you introduced a useless scope or increased the "cognitive complexity" to the code and have to explain it to a team leader who might not understand why you did that.
- jrockway 5y agoI guess don't use a C99 linter on a C89 codebase?
- hn_go_brrrrr 5y agoA team lead who does not understand that does not have the technical chops to be a team lead.
- lazide 5y agoDoesn’t mean they aren’t still your team lead though!
- staticassertion 5y agoShould we really be making decisions with people like that in mind?
- lazide 5y agoIf they are your team lead, would you have a choice?
- 5y ago
- synergy20 5y agohmm I submitted the same article 10 hours ago and not got picked up, where is the algorithm.
- chmaynard 5y agoWelcome to HN. This happens all the time. I added 'Linux' to the title, which attracted attention.
- tomcam 5y agoThis has happened to me a number of times! I think time of day has a heavier influence than we might think. Submitting is only part of the algorithm. Both vote count and velocity of votes are really important too.
- TheDesolate0 5y ago
- the__alchemist 5y agoI hope this isn't too much of a derail. I'm not proficient in C, and am translating a C module to Rust. My biggest complaint is there's so much DRY! Functions, variables etc are all prefixed with the module names, presumably due to lack of namespaces. The `.c` vs `.h` dichotomy is also DRY. The subset language that uses `#` is also a bit of a mess.
- Jtsummers 5y agoYou're using DRY oddly, but I presume you mean "there is so much duplication" (which is the opposite of DRY)? For the .c/.h part, it's because of use (or intended use). Header files are meant to be specifications (though a lot of implementation ends up in them, annoyingly). It actually is an example of DRY thanks to C's need to forward declare things. You can't call a function the compiler doesn't know about, for instance, so you declare (not define) it in the header if it's defined in an external module. If you didn't have the headers, you'd need to copy/paste or handwrite the declarations everywhere.
- the__alchemist 5y agoYou're right - I was referring to DRY violations. Why do you think there needs to be a declaration beyond the definition? The definition is enough information for the compiler, and having both is a DRY violation.
- Jtsummers 5y agoYou need the declarations because the compiler requires it, it's not something that I just thought up. If you don't, then you get two different declarations for bar in the following. The one you intended (char bar(int)) and the one you didn't (int bar()): int foo(int n) { char c = bar(n); ... } char bar(int n) { ... } The definition is not enough information for the compiler in a case like this, which is also essentially the case for any externally defined function. The compiler doesn't know anything about those unless its declaration is provided, which is what's in the header files.
- sfblah 5y agoCouldn’t they solve that macro issue using C89 by just having the macro create a block around the loop, and then declare the variable at the top of the block?
- mlindner 5y agoAnyone who insists on C89 is just talking nonsense. There are zero downsides to C99 and if you are using C89 you should not be.
- asveikau 5y ago~7 years ago you needed c89 to port to MS's compiler. But they brought some of that up to speed. I would not be surprised if there is some niche environment somewhere that needs c89. Not any mainstream desktop, server or phone though.
- yyyk 5y agoC99 added support for VLAs which are a mistake. Fortunately, Linux stopped using VLAs a while ago.
- deleted 5y ago[deleted]
- pabs3 5y agoI wonder what the implications of this are for Bootstrappable Builds. I guess they will just need a longer GCC versions bridge before getting to the step of building Linux. https://bootstrappable.org/ https://bootstrappable.org/
- rrauenza 5y agoI'm trying to understand how this linked list works -- struct list_head { struct list_head *next, *prev; }; struct foo { int fooness; struct list_head list; }; struct foo *iterator; list_for_each_entry(iterator, &foo_list, list) { do_something_with(iterator); } If we are walking iterator->list->next ... how do we get the pointer of the next enclosing foo struct? Are they doing pointer arithmetic to get the beginning of the struct from the list field offset and casting it to foo? Ah -- That does seem like what they do: #define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) #define list_entry(ptr, type, member) \ container_of(ptr, type, member) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
- kragen 5y agoYeah, standard hack for intrusive linked lists in C and similar languages.
- dddnzzz334 5y agoHow do I learn all these pointer hacks in C?
- db48x 5y agohttps://en.cppreference.com/w/cpp/types/offsetof https://en.cppreference.com/w/cpp/types/offsetof
- simias 5y agoI always strongly disliked the kernel's approach to macros (especially how they try to masquerade as everything but macros with their lowercase names). More than once I wasted time debugging code because I didn't realize that a macro was involved (special mention for the cases where depending on the compilation flags a symbol can sometimes expand to a macro and sometimes something else). I suppose in the case of list handling there's not really a good alternative though. If C had lambdas we could use inline functions instead but that's not a thing. Still think it ought to have been uppercase though.