Linux/Unix系统下的线程安全IO

Posted sesiria

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux/Unix系统下的线程安全IO相关的知识,希望对你有一定的参考价值。

SIO Packages (Signal-Safe IO)

/*************************************************************
 * The Sio (Signal-safe I/O) package - simple reentrant output
 * functions that are safe for signal handlers.
 *************************************************************/

/* Private sio functions */

/* $begin sioprivate */
/* sio_reverse - Reverse a string (from K&R) */
static void sio_reverse(char s[])

    int c, i, j;

    for (i = 0, j = strlen(s)-1; i < j; i++, j--) 
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    


/* sio_ltoa - Convert long to base b string (from K&R) */
static void sio_ltoa(long v, char s[], int b) 

    int c, i = 0;
    int neg = v < 0;

    if (neg)
	v = -v;

    do   
        s[i++] = ((c = (v % b)) < 10)  ?  c + '0' : c - 10 + 'a';
     while ((v /= b) > 0);

    if (neg)
	s[i++] = '-';

    s[i] = '\\0';
    sio_reverse(s);


/* sio_strlen - Return length of string (from K&R) */
static size_t sio_strlen(char s[])

    int i = 0;

    while (s[i] != '\\0')
        ++i;
    return i;

/* $end sioprivate */

/* Public Sio functions */
/* $begin siopublic */

ssize_t sio_puts(char s[]) /* Put string */

    return write(STDOUT_FILENO, s, sio_strlen(s)); //line:csapp:siostrlen


ssize_t sio_putl(long v) /* Put long */

    char s[128];
    
    sio_ltoa(v, s, 10); /* Based on K&R itoa() */  //line:csapp:sioltoa
    return sio_puts(s);


void sio_error(char s[]) /* Put error message and exit */

    sio_puts(s);
    _exit(1);                                      //line:csapp:sioexit

/* $end siopublic */

/*******************************
 * Wrappers for the SIO routines
 ******************************/
ssize_t Sio_putl(long v)

    ssize_t n;
  
    if ((n = sio_putl(v)) < 0)
	sio_error("Sio_putl error");
    return n;


ssize_t Sio_puts(char s[])

    ssize_t n;
  
    if ((n = sio_puts(s)) < 0)
	sio_error("Sio_puts error");
    return n;


void Sio_error(char s[])

    sio_error(s);

RIO Pakcages(Robust I/O functions)

/****************************************
 * The Rio package - Robust I/O functions
 ****************************************/

/*
 * rio_readn - Robustly read n bytes (unbuffered)
 */
/* $begin rio_readn */
ssize_t rio_readn(int fd, void *usrbuf, size_t n) 

    size_t nleft = n;
    ssize_t nread;
    char *bufp = usrbuf;

    while (nleft > 0) 
	if ((nread = read(fd, bufp, nleft)) < 0) 
	    if (errno == EINTR) /* Interrupted by sig handler return */
		nread = 0;      /* and call read() again */
	    else
		return -1;      /* errno set by read() */ 
	 
	else if (nread == 0)
	    break;              /* EOF */
	nleft -= nread;
	bufp += nread;
    
    return (n - nleft);         /* Return >= 0 */

/* $end rio_readn */

/*
 * rio_writen - Robustly write n bytes (unbuffered)
 */
/* $begin rio_writen */
ssize_t rio_writen(int fd, void *usrbuf, size_t n) 

    size_t nleft = n;
    ssize_t nwritten;
    char *bufp = usrbuf;

    while (nleft > 0) 
	if ((nwritten = write(fd, bufp, nleft)) <= 0) 
	    if (errno == EINTR)  /* Interrupted by sig handler return */
		nwritten = 0;    /* and call write() again */
	    else
		return -1;       /* errno set by write() */
	
	nleft -= nwritten;
	bufp += nwritten;
    
    return n;

/* $end rio_writen */


/* 
 * rio_read - This is a wrapper for the Unix read() function that
 *    transfers min(n, rio_cnt) bytes from an internal buffer to a user
 *    buffer, where n is the number of bytes requested by the user and
 *    rio_cnt is the number of unread bytes in the internal buffer. On
 *    entry, rio_read() refills the internal buffer via a call to
 *    read() if the internal buffer is empty.
 */
/* $begin rio_read */
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)

    int cnt;

    while (rp->rio_cnt <= 0)   /* Refill if buf is empty */
	rp->rio_cnt = read(rp->rio_fd, rp->rio_buf, 
			   sizeof(rp->rio_buf));
	if (rp->rio_cnt < 0) 
	    if (errno != EINTR) /* Interrupted by sig handler return */
		return -1;
	
	else if (rp->rio_cnt == 0)  /* EOF */
	    return 0;
	else 
	    rp->rio_bufptr = rp->rio_buf; /* Reset buffer ptr */
    

    /* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
    cnt = n;          
    if (rp->rio_cnt < n)   
	cnt = rp->rio_cnt;
    memcpy(usrbuf, rp->rio_bufptr, cnt);
    rp->rio_bufptr += cnt;
    rp->rio_cnt -= cnt;
    return cnt;

/* $end rio_read */

/*
 * rio_readinitb - Associate a descriptor with a read buffer and reset buffer
 */
/* $begin rio_readinitb */
void rio_readinitb(rio_t *rp, int fd) 

    rp->rio_fd = fd;  
    rp->rio_cnt = 0;  
    rp->rio_bufptr = rp->rio_buf;

/* $end rio_readinitb */

/*
 * rio_readnb - Robustly read n bytes (buffered)
 */
/* $begin rio_readnb */
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n) 

    size_t nleft = n;
    ssize_t nread;
    char *bufp = usrbuf;
    
    while (nleft > 0) 
	if ((nread = rio_read(rp, bufp, nleft)) < 0) 
            return -1;          /* errno set by read() */ 
	else if (nread == 0)
	    break;              /* EOF */
	nleft -= nread;
	bufp += nread;
    
    return (n - nleft);         /* return >= 0 */

/* $end rio_readnb */

/* 
 * rio_readlineb - Robustly read a text line (buffered)
 */
/* $begin rio_readlineb */
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen) 

    int n, rc;
    char c, *bufp = usrbuf;

    for (n = 1; n < maxlen; n++)  
        if ((rc = rio_read(rp, &c, 1)) == 1) 
	    *bufp++ = c;
	    if (c == '\\n') 
                n++;
     		break;
            
	 else if (rc == 0) 
	    if (n == 1)
		return 0; /* EOF, no data read */
	    else
		break;    /* EOF, some data was read */
	 else
	    return -1;	  /* Error */
    
    *bufp = 0;
    return n-1;

/* $end rio_readlineb */

/**********************************
 * Wrappers for robust I/O routines
 **********************************/
ssize_t Rio_readn(int fd, void *ptr, size_t nbytes) 

    ssize_t n;
  
    if ((n = rio_readn(fd, ptr, nbytes)) < 0)
	unix_error("Rio_readn error");
    return n;


void Rio_writen(int fd, void *usrbuf, size_t n) 

    if (rio_writen(fd, usrbuf, n) != n)
	unix_error("Rio_writen error");


void Rio_readinitb(rio_t *rp, int fd)

    rio_readinitb(rp, fd);
 

ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n) 

    ssize_t rc;

    if ((rc = rio_readnb(rp, usrbuf, n)) < 0)
	unix_error("Rio_readnb error");
    return rc;


ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen) 

    ssize_t rc;

    if ((rc = rio_readlineb(rp, usrbuf, maxlen)) < 0)
	unix_error("Rio_readlineb error");
    return rc;
 

以上是关于Linux/Unix系统下的线程安全IO的主要内容,如果未能解决你的问题,请参考以下文章

Linux/Unix系统下的线程安全IO

Linux/Unix系统下的线程安全IO

基础篇:Linux/Unix下的不同IO模型

巧用linux云服务器下的的/dev/shm/,避开磁盘IO不给力!

Linux/Unix 使用inotify,hook函数来监控文件事件

Linux/Unix 使用inotify,hook函数来监控文件事件