9. Programming on Unix-systems: Xenix, HP-UX, BSD, and Linux

This is where things can be more fun. I will discuss the extensive possibilities with Linux in another section, this section is about the things that are common to all systems in the Unix family.

Serial ports are handled via the kernel, and are opened as device files. Reading and writing here moves data, and there are select(2) and ioctl(2) system calls for setting baud rates etc. The interface is completely different from the "bare metal" discussed for DOS above. The mechanism for accessing the control wires (RTS CTS CD DSR DTR RI) is different, and the capabilities available depend on manufacturers and the actual hardware, in addition to the opeating system. For example, some of the HP9000 serial ports have no control lines at all, others may have additional ones; while the set of extra lines available on the Picotux have to be handled in a different way altogether.

Then, there is something funny going on with the RI input on DELL hardware, where it seems to work slightly differently than elsewhere, so it becomes less useful.

The device name, such as /dev/tty112, is opened as a file in standard UNIX fashion. The ioctl() call is used to set parameters, and the read() function is used to look for data, as well as reading. The write() function is used for data output:

        int hx;
        struct termio ti;

        hx = open("/dev/tty112", O_RDWR | O_NDELAY);

        ioctl(hx, TCGETA, &ti);
        /* Parameters in the termio struct are changed. These define 
            Baud-rate and may allow control of the RTS and DTR lines. */
        ioctl(hx, TCSETA, &ti);

        write(hx, txt, 1);
        x = read(hx, txt, 1);

        close(hx);

The O_NDELAY flag of open() makes the read-function calls non-blocking. This makes reading troublesome on Linux systems, but works well on the other systems such as hp-ux and BSD. An alternative which I have tried, and find that works reasonably well on all systems, is to use select(2) where some bits will be set indicating data pending.

In the following, the fd_set and struct timeval data objects and the FD_ZERO() and FD_SET() macros are defined in include files such as <termio.h> and <fcntl.h>. These exist on hp-ux at least, as well as on Linux.

int serreadtimeout(int eid, long ts, long tu, char *rx, int rxcount, int *nrd)
{
    fd_set rfds;
    struct timeval tv;
    int retval;

    tv.tv_sec = ts;
    tv.tv_usec = tu; 
    FD_ZERO(&rfds); 
    FD_SET(eid, &rfds); 
    retval = select(eid+1, &rfds, NULL, NULL, &tv); 

    if(retval)
    {
        *nrd = read(eid, rx, rxcount);
    }
    return(retval);
}

To 0. Introduction

To 8. 32-bit programming on Windows NT/2000/XP.

To 10. Programming on Unix-systems: Linux

Table of ASCII codes

To index page