30

From the Wikipedia article on reserved device names

... and the CLOCK$ (still named CLOCK in some issues of MS-DOS 2.11) clock device were introduced with DOS 2.0, ...

Why was is necessary to add a $ character to this device name?
And why didn't they name this device CLK which would have made sense in a list such as CON, AUX, PRN, LST, NUL?

Microsoft advices against using these device names as filenames regardless of extension. Perhaps too many users couldn't resist having CLOCK as a filename?

6
  • 3
    What was the name of the clock application that was in Windows 1.0? I'd guess there's a fair chance it was called CLOCK ... Apr 3 at 21:45
  • 5
    @another-dave At least in Windows 3.1, I see the WINDOWS directory has a CLOCK.EXE and a CLOCK.INI.
    – Sep Roland
    Apr 3 at 21:56
  • 4
    I (mercifully) have forgotten the vagaries of the DOS FAT implementation. Wasn't it the case that if the filename was a known device name, any extension specified by the program was ignored? If so, that's surely the answer. Apr 3 at 22:28
  • 3
    @another-dave Except that would have been an anachronism, because Windows 1.0 was released when DOS 3.10 was already available, so it couldn’t have influenced the development of DOS 2. On the other and, perhaps other, older clock apps already started to appear (or were expected to appear)… Apr 4 at 6:51
  • 4
    Related reading: <os2museum.com/wp/from-a-feature-to-a-bug>. Apr 4 at 11:04

3 Answers 3

38

Quick partial answer:

  • CON, LST, PRN and AUX (*1) are names inherited from CP/M, either direct form its BIOS or CP/M's main file handling utility PIP (*2). NUL was add with DOS.

  • DOS 1.x added additional names for installable interfaces like LPT1..4 or COM1..4

  • CLOCK was introduced with DOS 2.0

But DOS 2.0 added loadable device drivers as well, each able to bring any arbitrary name of its own. Basically not a big issue, but it would make it quite hard for MS to make sure that any new name they may come up in future versions has not been taken by any third party driver.

To solve this MS defined that all future (MS) device names, except for the DOS1.x like names, which may be present at boot, has to include a $ sign as last character (*3).

Problem solved - except, that definition was only made after DOS 2.0 was published, so CLOCK came preinstalled in DOS 2.0 without a $-suffix, a lapse fixed in DOS 2.1.

CLOCK$ was, BTW, not the only one added that way, so was SCREEN$, KEYBD$ or MOUSE$.


*1 - there were a few more, like RDR (Reader) or PCH (Punch), that got added over time, but didn't make it to MS-DOS

*2 - CP/M PIP in turn inherited them from RSTS/E.

*3 - They had to pick one that had no other meaning at the time and would be valid wherever a device name is possible.

16
  • 2
    And RSTS inherited them from TOPS-10. Apr 3 at 23:42
  • 4
    Incidentally, the 'symbols with a dollar sign are reserved to us' was also a DEC convention, certainly on RSX-11M systems (I forget about RSTS). Apr 4 at 0:56
  • 3
    ‘To solve this MS defined that all future (MS) device names, except for the DOS1.x like names, which may be present at boot, has to include a $ sign as last character’ — where did they define that? Why didn’t devices like XMSXXXX0 (HIMEM.SYS), EMMXXXX0 (EMM386.EXE), SETVERXX (SETVER.EXE), _doubleB (SMARTDRV.EXE) or MSCD0001 (commonly used with MSCDEX.EXE) obey this? Apr 4 at 6:35
  • 4
    @MarkMorganLloyd CLOCK$ also needs to handle a stream of characters; specifically, sequences of three words. Try COPY CLOCK$ CON ;-). Apr 4 at 10:07
  • 3
    @Raffzahn Yes, it /is/ a standard device, but in this type of situation a name and the standard stream API (not that that term was in common use in the early 80s) is more a convenience than a requirement. And in DOS the ioctl() function was woefully underused: it was far more common to find that once a driver or TSR was in memory it used some proprietary interface... which of course is where the Blessed Ralph's magnum opus was important. Apr 4 at 10:52
25

As Raffzahn explains, the clock device driver was added in DOS 2.0. CON, AUX, etc. were device names already present in DOS 1.0, some of them even earlier in CP/M; these names couldn’t be changed to preserve backwards compatibility. Of all the standard (in-kernel) device drivers, CLOCK$ is the only one which wasn’t already present in DOS 1.0.

An important subtlety in DOS is that opening a file or device (interrupt 0x21, service 0x3D when using file handles) will open a device in preference to a file for any file name matching a device, ignoring the file extension. Opening NUL, NUL.TXT etc. will all result in opening the NUL device driver, not a file on disk. Thus, any new device driver effectively replaces any file using the same name, in any directory, regardless of extension.¹ CP/M required colons (PRN: etc.) to identify device names, but this requirement was dropped in MS-DOS, which merged the namespaces.

As far as the clock device goes, DOS itself doesn’t care what the name of the device is; the clock device is identified by a specific bit in the device driver attributes (bit 3). The DOS reference manual mentions this:

MS-DOS assumes that some sort of clock is available in the system. This may either be a CMOS real-time clock or an interval timer that is initialized at boot time by the user. The CLOCK device defines and performs functions like any other character device, except that it is identified by a bit in the attribute word. The DOS uses this bit to identify it; consequently, the CLOCK device may take any name. The IBM implementation uses the name $CLOCK so as not to conflict with existing files named clock.

It would appear that the CLOCK device name was chosen, and then someone realised that it would create conflicts with any existing file matching CLOCK.*; to avoid that, the driver was renamed to $CLOCK in PC DOS, and CLOCK$ in MS-DOS (which was also the name used in DR DOS), but not before some releases ended up using that name in the wild.

Without this change, people with files named CLOCK.EXE or CLOCK.TXT etc. on floppy disks would lose access to them when they switched from DOS 1 to DOS 2. CON, NUL, AUX etc. don’t have this problem because no one would ever have been able to create such files on a PC using DOS (except by modifying the directory entry directly on disk).

All this is the reason why installable character device drivers use variously-decorated names: MSCD0001 and so on for MSCDEX, EMMXXXX0 for EMM386, the list goes on.


¹ Ignoring both the directory and extension were deliberate design decisions. DOS 1 programs didn’t know about directories, and expected to be able to open devices anywhere (see “From a Feature to a Bug” on OS/2 Museum). Some programs (particularly those ported from CP/M) also forcibly applied their own extension to whatever was provided by the user, so extensions had to be ignored so that devices could be used (being able to ask a program to use PRN or COM1 instead of a regular file could be very useful in some circumstances). DOS supports a Unix-style \DEV virtual directory, but that never gained much traction.

0
5

The $ suffix was meant to fence off the Microsoft-reserved namespace. It works the way the __ prefix fences off the implementation-reserved namespace in C and C++.

Similar to C and C++, DOS had a long legacy. The legacy devices inherited from CP/M and DOS 1.x were kept unchanged, as everyone writing custom device drivers would be aware of them. The MS-reserved namespace was there so that DOS-specific device names would not clash with those provided by 3rd-party drivers.

As for why some implementation-provided drivers, like XMM/EMS, didn't have $-prefix: they had a numeric suffix... This was another part of the device namespace MS has fenced-off for their own use. Those things weren't always written down, and absent a clear design documentation stating these constraints, the implementers often did things "similar but not quite".

Speaking of XMM and EMS specifically: the named device files wouldn't be used for anything but detecting the presence of the drivers. To use the services, you'd directly use service-specific entry points, e.g. INT 67h for EMM services. The name-based device detection was a bit more robust, as in some circumstances the non-installed interrupt vectors could point to garbage. The file-handle based access to performance-critical services such as EMM had too much overhead in the early days of DOS. DOS+BIOS made the decision to have quite a bit of system device access done by dedicated APIs, and not using the character device abstraction. Which, admittedly, was a shame.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.