Problem 16. What’s the difference between soft link and hard link file?

Ans:

Hard link file is nothing but a regular file which pair its name with an inode which is pointed by other files(hard link file or other regular file) too. Accessing a hard link file only takes one time to access the file pointed by inode number.

Soft link file is a file whose data chunk contains nothing but an another file’s pathname. So when accessing the file through a soft link, you need to access the file system two times. One for reading the content of the soft link file and the other for reading the file pointed by the soft link.

Problem 17. what’s the differences among real uid, effective uid, a saved uid, and a filesystem uid?

Ans:

real uid: is always that of the user who started the process(开启进程).

effective uid:  may change under various rules to allow a process to execute with

the rights of different users(运行进程).

saved uid : stores the original effective uid; its value is used in deciding what effective uid values the user may switch to(保存当前的有效用户ID).

filesystem uid: is usually equal to the effective uid, used to verify file access.

Problem 18. A common mistake in checking errno is to forget that any library or system call can modify it.

Ans:

For example, this code is buggy:

if (fsync (fd) == -1) {

fprintf (stderr, "fsync failed!/n");

if (errno == EIO)

fprintf (stderr, "I/O error on %d!/n", fd);

}

If you need to preserve the value of errno across function invocations, save it:

if (fsync (fd) == -1) {

int err = errno;

fprintf (stderr, "fsync failed: %s/n", strerror (errno));

if (err == EIO) {

/* if the error is I/O-related, jump ship */

fprintf (stderr, "I/O error on %d!/n", fd);

exit (EXIT_FAILURE);

}

}

PS: errno是一个全局变量,任何函数调用之后都有可能修改了它的值,所以连续调用两个函数时,必须保存每次函数调用后的errno值,以便能进行相应的错误检测。

In single-threaded programs, errno is a global variable. In multithreaded programs, however, errno is stored per-thread, and is thus thread-safe.

Problem 19. How to use the read() function safely?

Ans:

ssize_t ret;

while (len != 0 && (ret = read (fd, buf, len)) != 0) {

        if (ret == -1) {

                if (errno == EINTR)

                         continue;

                perror ("read");

                break;

        }

        len -= ret;

        buf += ret;

}

PS:

Read函数调用后的产生的结果有以下几种:

1. The call returns a value equal to len. All len read bytes are stored in buf. The

results are as intended.

2. The call returns a value less than len, but greater than zero. This can occur because a signal interrupted the read midway, an error occurred in the middle of the read, more than zero, but less than len bytes’ worth of data was available, or EOF was reached before len bytes were read. Reissuing the read (with correspondingly updated buf and len values) will read the remaining bytes into the rest of the buffer, or indicate the cause of the problem.

3. The call returns 0. This indicates EOF. There is nothing to read.

4. The call returns 0. This indicates EOF. There is nothing to read.

5. The call returns -1, and errno is set to EINTR. This indicates that a signal was

received before any bytes were read. The call can be reissued.

6. The call returns -1, and errno is set to EAGAIN. This indicates that the read would block because no data is currently available, and that the request should be reissued later. This happens only in nonblocking mode.

7. The call returns -1, and errno is set to a value other than EINTR or EAGAIN. This

indicates a more serious error.

An Example for Write():

ssize_t ret, nr;

while (len != 0 && (ret = write (fd, buf, len)) != 0) {

        if (ret == -1) {

                 if (errno == EINTR)

                         continue;

                 perror ("write");

                 break;

        }

        len -= ret;

        buf += ret;

}

Problem 20. How to use select(), pselect(), poll, ppoll() and epoll()?

Ans:

1.  select() example:

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

int select (int n,

            fd_set  *readfds,

            fd_set  *writefds,

            fd_set  *exceptfds,

            struct  timeval *timeout);

FD_CLR(int fd, fd_set *set);

FD_ISSET(int fd, fd_set *set);

FD_SET(int fd, fd_set *set);

FD_ZERO(fd_set *set);

#include  <stdio.h>

#include  <sys/time.h>

#include  <sys/types.h>

#include  <unistd.h>

#define TIMEOUT 5        /* select timeout in seconds */

#define BUF_LEN 1024     /* read buffer in bytes */

int main (void)

{

struct timeval tv;

fd_set readfds;

int ret;

/* Wait on stdin for input. */

FD_ZERO(&readfds);

FD_SET(STDIN_FILENO, &readfds);

/* Wait up to five seconds. */

tv.tv_sec = TIMEOUT;

tv.tv_usec = 0;

/* All right, now block! */

ret = select (STDIN_FILENO + 1,

&readfds,

NULL,

NULL,

&tv);

if (ret == -1) {

perror ("select");

return 1;

} else if (!ret) {

printf ("%d seconds elapsed./n", TIMEOUT);

return 0;

}

/*

* Is our file descriptor ready to read?

* (It must be, as it was the only fd that

* we provided and the call returned

* nonzero, but we will humor ourselves.)

*/

if (FD_ISSET(STDIN_FILENO, &readfds)) {

char buf[BUF_LEN+1];

int len;

/* guaranteed to not block */

len = read (STDIN_FILENO, buf, BUF_LEN);

if (len == -1) {

perror ("read");

return 1;

}

if (len) {

buf[len] = '/0';

printf ("read: %s/n", buf);

}

return 0;

}

fprintf (stderr, "This should not happen!/n");

return 1;

}

PS:Portable sleeping with select( )

struct timeval tv;

tv.tv_sec = 0;

tv.tv_usec = 500;

/* sleep for 500 microseconds */

select (0, NULL, NULL, NULL, &tv);

There are three differences between pselect( ) and select( ):

1. pselect( ) uses the timespec structure, not the timeval structure, for its timeout

parameter. The timespec structure uses seconds and nanoseconds, not seconds

and microseconds, providing theoretically superior timeout resolution. In prac-

tice, however, neither call reliably provides even microsecond resolution.

2. A call to pselect( ) does not modify the timeout parameter. Consequently, this

parameter does not need to be reinitialized on subsequent invocations.

3. The select( ) system call does not have the sigmask parameter. With respect to

signals, when this parameter is set to NULL, pselect( ) behaves like select( ).

PS:

Until the 2.6.16 kernel, the Linux implementation of pselect( ) was not a system

call, but a simple wrapper around select( ), provided by glibc. This wrapper mini-

mized—but did not totally eliminate—the risk of this race condition occurring. With the introduction of a true system call, the race is gone.

2.  poll() example

#include <sys/poll.h>

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

 

struct pollfd {

        int fd;                  /* file descriptor */

        short events;        /* requested events to watch */

        short revents;           /* returned events witnessed */

};

#include <stdio.h>

#include <unistd.h>

#include <sys/poll.h>

#define TIMEOUT 5       /* poll timeout, in seconds */

int main (void)

{

struct pollfd fds[2];

int ret;

/* watch stdin for input */

fds[0].fd = STDIN_FILENO;

fds[0].events = POLLIN;

/* watch stdout for ability to write (almost always true) */

fds[1].fd = STDOUT_FILENO;

fds[1].events = POLLOUT;

/* All set, block! */

ret = poll (fds, 2, TIMEOUT * 1000);

if (ret == -1) {

perror ("poll");

return 1;

}

if (!ret) {

printf ("%d seconds elapsed./n", TIMEOUT);

return 0;

}

if (fds[0].revents & POLLIN)

printf ("stdin is readable/n");

if (fds[1].revents & POLLOUT)

printf ("stdout is writable/n");

return 0;

}

ppoll( )

Linux provides a ppoll( ) cousin to poll( ), in the same vein as pselect( ). Unlike

pselect( ), however, ppoll( ) is a Linux-specific interface:

#define _GNU_SOURCE

#include <sys/poll.h>

int ppoll (struct pollfd *fds,

nfds_t nfds,

const struct timespec *timeout,

const sigset_t *sigmask);

As with pselect( ), the timeout parameter specifies a timeout value in seconds and

nanoseconds, and the sigmask parameter provides a set of signals for which to wait.

epoll()

An epoll context is created via epoll_create( ):

#include <sys/epoll.h>

int epoll_create (int size)

The epoll_ctl( ) system call can be used to add file descriptors to and remove file

descriptors from a given epoll context:

#include <sys/epoll.h>

int epoll_ctl (int epfd,

int op,

int fd,

struct epoll_event *event);

The header <sys/epoll.h> defines the epoll_event structure as:

struct epoll_event {

_ _u32 events; /* events */

union {

void *ptr;

int fd;

_ _u32 u32;

_ _u64 u64;

} data;

};

The system call epoll_wait( ) waits for events on the file descriptors associated with the given epoll instance:

#include <sys/epoll.h>

int epoll_wait (int epfd,

struct epoll_event *events,

int maxevents,

int timeout);

ps:如果timeout为0,函数立即返回,如果timeout为-1,仅在检测到事件发生时,函数才会返回。

example:

int epfd;

epfd = epoll_create (100); /* plan to watch ~100 fds */

if (epfd < 0)

perror ("epoll_create");

/*add a new watch on the file associated with fd to the epoll instance epfd,*/

struct epoll_event event;

int ret;

event.data.fd = fd; /* return the fd to us later */

event.events = EPOLLIN | EPOLLOUT;

ret = epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &event);

if (ret)

perror ("epoll_ctl");

/*modify an existing event on the file associated with fd on the epoll instance epfd*/

struct epoll_event event;

int ret;

event.data.fd = fd; /* return the fd to us later */

event.events = EPOLLIN;

ret = epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &event);

if (ret)

perror ("epoll_ctl");

/*remove an existing event on the file associated with fd from the epoll

instance epfd*/

struct epoll_event event;

int ret;

ret = epoll_ctl (epfd, EPOLL_CTL_DEL, fd, &event);

if (ret)

perror ("epoll_ctl");

PS:此时event参数可以为NULL,但在2.6.9之前,此函数要求不管在什么情况下,event都不能为空,所以为了保持兼容性,传递一个非空的event参数。

/*A full epoll_wait( ) example*/

#define MAX_EVENTS    64

struct epoll_event *events;

int nr_events, i, epfd;

events = malloc (sizeof (struct epoll_event) * MAX_EVENTS);

if (!events) {

perror ("malloc");

return 1;

}

nr_events = epoll_wait (epfd, events, MAX_EVENTS, -1);

if (nr_events < 0) {

perror ("epoll_wait");

free (events);

return 1;

}

for (i = 0; i < nr_events; i++) {

printf ("event=%ld on fd=%d/n",

events[i].events,

events[i].data.fd);

/*

* We now can, per events[i].events, operate on

* events[i].data.fd without blocking.

*/

}

free (events);

PS:

poll( ) Versus select( )

Although they perform the same basic job, the poll( ) system call is superior to

select( ) for a handful of reasons:

• poll( ) does not require that the user calculate and pass in as a parameter the

value of the highest-numbered file descriptor plus one.

• poll( ) is more efficient for large-valued file descriptors. Imagine watching a sin-

gle file descriptor with the value 900 via select( )—the kernel would have to

check each bit of each passed-in set, up to the 900th bit.

• select( )’s file descriptor sets are statically sized, introducing a tradeoff: they are

small, limiting the maximum file descriptor that select( ) can watch, or they are

inefficient. Operations on large bitmasks are not efficient, especially if it is not

known whether they are sparsely populated.* With poll( ), one can create an

array of exactly the right size. Only watching one item? Just pass in a single

structure.

• With select( ), the file descriptor sets are reconstructed on return, so each sub-

sequent call must reinitialize them. The poll( ) system call separates the input

(events field) from the output (revents field), allowing the array to be reused

without change.

• The timeout parameter to select( ) is undefined on return. Portable code needs

to reinitialize it. This is not an issue with pselect( ), however.

The select( ) system call does have a few things going for it, though:

• select( ) is more portable, as some Unix systems do not support poll( ).

• select( ) provides better timeout resolution: down to the microsecond. Both

ppoll( ) and pselect( ) theoretically provide nanosecond resolution, but in prac-

tice, none of these calls reliably provides even microsecond resolution.

Superior to both poll( ) and select( ) is the epoll interface, a Linux-specific multi-

plexing I/O solution

PS:how to safely use rewind() function?

errno = 0;

rewind (stream);

if (errno)

/* error */

由于rewind()函数没有返回值,所以不能通过返回值来进行错误处理,必须通过全局变量errno,所以调用之前必须置errno为0.

为了确保数据流中的数据在文件关闭之前确实写入到了磁盘中,必须调用以下函数:

fflush();//确保用户程序缓冲区的数据写入内核中

fsync();//确保内核缓冲区的数据写入到磁盘中。

转载于:https://my.oschina.net/fuyajun1983cn/blog/263823

问题集锦(16-20)相关推荐

  1. 分享一个有趣的学习方法,欢迎一起探讨如何提高学习兴趣作者:1-2-3 来源:博客园 发布时间:2009-03-09 16:20 阅读:2820 次 原文链接 [收藏]

    分享一个有趣的学习方法,欢迎一起探讨如何提高学习兴趣 作者:1-2-3  来源:博客园  发布时间:2009-03-09 16:20  阅读:2820 次  原文链接   [收藏]   有些人似乎天生 ...

  2. ETIMEDOU 104.16.20.35:443(已解决)

    npm ERR! network request to https://registry.npmjs.org/@nodelib%2ffs.stat , reason: connect ETIMEDOU ...

  3. 2016年8月19日 星期五 --出埃及记 Exodus 16:20

    2016年8月19日 星期五 --出埃及记 Exodus 16:20 However, some of them paid no attention to Moses; they kept part ...

  4. [问题已处理]-k8s报错Error from server- error dialing backend- dial tcp 172.16.20.88-10250

    导语:重启服务器之后,节点连接pod报错Error from server: error dialing backend: dial tcp 172.16.20.88:10250 现象是pod都无法进 ...

  5. Python 人工智能:16~20

    原文:Artificial Intelligence with Python 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自[ApacheCN 深度学习 译文集],采用译后编辑(MTPE) ...

  6. java代码优化的方法和准则_编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议16~20)...

    建议16:易变业务使用脚本语言编写 Java世界一直在遭受着异种语言的入侵,比如PHP,Ruby,Groovy.Javascript等,这些入侵者都有一个共同特征:全是同一类语言-----脚本语言,它 ...

  7. Python 小型项目大全 16~20

    #16 钻石 原文:http://inventwithpython.com/bigbookpython/project16.html 这个程序的特点是一个小算法,用于绘制各种尺寸的 ASCII 艺术画 ...

  8. Python3 编程实例(16 - 20)

    实例16 题目 输出指定格式的日期: 分析 没啥说的,直接调用 datetime 模块即可: 代码 #!/usr/bin/env python # -*- coding: utf-8 -*- # @T ...

  9. 转载--编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议16~20)...

    阅读目录 建议16:易变业务使用脚本语言编写 建议17:慎用动态编译 建议18:避免instanceof非预期结果 建议19:断言绝对不是鸡肋 建议20:不要只替换一个类 回到顶部 建议16:易变业务 ...

  10. SQL 必知必会 50 题(16 - 20)

    SQL16 检索产品名称和描述(一) 描述 Products表 prod_name prod_desc a0011 usb a0019 iphone13 b0019 gucci t-shirts c0 ...

最新文章

  1. 手机游戏深化、改革。
  2. 设计模式复习-解释器模式
  3. 广州科目三路考经历与注意事项分享
  4. Javascript ES6 Promise同步读取文件(使用async、await)
  5. 连通域的原理与Python实现
  6. matlab一个figure画多个子图,和多个figure画多个图。
  7. UCOII信号量与消息邮箱
  8. 基带传输编码方式HDB3码的快速编码步骤、原理及举例
  9. poj 2387 最短路 spfa 实现
  10. 大学如何自学计算机科学与技术?
  11. 用Keil工具搭建S3C2440编译环境
  12. 2018高中计算机竞赛,最新 | 2018年高中生各项竞赛时间一览表
  13. 如何使用Flutter封装即时通讯IM框架开发插件
  14. python image 垂直切割图片 验证码图片识别处理
  15. 国内可用的时间服务器
  16. r语言赋值为na_R语言中特殊值NaN、Inf 、NA、NULL
  17. 想知道CAD怎么转图片格式?跟我学会这几招就足够了
  18. ATTCK靶场系列(七)
  19. 手机号码归属地查询(php+redis)
  20. Windows服务优化(整理篇)

热门文章

  1. OEA 框架演示 - 快过原型的开发
  2. html字体颜色代码表
  3. SharePoint Application Page启用匿名访问
  4. SVM(支持向量机)之Hinge Loss解释
  5. Mac 安装 Eclipse
  6. Ubuntu Dapper 提速脚本
  7. 阿里云新一代关系型数据库 PolarDB 剖析
  8. C++模板之特化与偏特化详解
  9. 利用webpack和vue实现组件化
  10. C++ operator两种用法【转】