我爱编程

第1章——《Unix基础知识》

2018-06-21  本文已影响0人  alex_man

实验环境介绍

引言

以下会以知识点 + 代码实验的方式来进行讲解、总结

Unix体系结构

登录

注意:虽然《Unix环境高级编程》中使用了多种shell来做实验,但是我的笔记、实验中统一在bash环境下进行

文件和目录

输入和输出

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define BUFFSIZE(buf) (strlen(buf) + 1)

int
main(int argc, char *argv[])
{
    int n;
    char buf[] = "parent write to stdout\n";
    char buf2[] = "child write to stdout\n";

    pid_t pid = fork();
    if (pid < 0)
        printf("fork error\n");
    else if (pid) {
        /* 父进程 */
        n = write(STDOUT_FILENO, buf, BUFFSIZE(buf));
        printf("parent write %d bytes\n", n);
        if (n < 0)
            printf("parent write error\n");
    } else {
        /* 子进程 */
        n = write(STDOUT_FILENO, buf2, BUFFSIZE(buf2));
        printf("child write %d bytes\n", n);
        if (n < 0)
            printf("child write error\n");
    }
    exit(EXIT_SUCCESS);
}

result:
parent write to stdout
child write to stdout
parent write 24 bytes
child write 23 bytes

第3章再来详细说明不带缓冲的I/O函数

程序和进程

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    pid_t pid = getpid();
    printf("current pid is: %d\n", (long)pid);

    exit(EXIT_SUCCESS);
}

result:
current pid is: 33798

出错处理

// 这个是以前的定义
extern int errno;

// Linux支持多线程存取errno的定义
# ifndef __ASSEMBLER__
/* Function to get address of global `errno' variable.  */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));

#  if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value.  */
#  define errno (*__errno_location ())
#  endif
# endif /* !__ASSEMBLER__ */
      E2BIG          Argument list too long (POSIX.1)
      EACCES          Permission denied (POSIX.1)
      EADDRINUSE      Address already in use (POSIX.1)
      EADDRNOTAVAIL  Address not available (POSIX.1)
      EAFNOSUPPORT    Address family not supported (POSIX.1)
      EAGAIN          Resource temporarily unavailable (may be the same value as EWOULDBLOCK) (POSIX.1)
      EALREADY        Connection already in progress (POSIX.1)
      EBADE          Invalid exchange
      EBADF          Bad file descriptor (POSIX.1)
      EBADFD          File descriptor in bad state
      EBADMSG        Bad message (POSIX.1)
      EBADR          Invalid request descriptor
      EBADRQC        Invalid request code
      EBADSLT        Invalid slot
      EBUSY          Device or resource busy (POSIX.1)
      ECANCELED      Operation canceled (POSIX.1)
      ECHILD          No child processes (POSIX.1)
      ECHRNG          Channel number out of range
      ECOMM          Communication error on send
      ECONNABORTED    Connection aborted (POSIX.1)
      ECONNREFUSED    Connection refused (POSIX.1)
      ECONNRESET      Connection reset (POSIX.1)
      EDEADLK        Resource deadlock avoided (POSIX.1)
      EDEADLOCK      Synonym for EDEADLK
      EDESTADDRREQ    Destination address required (POSIX.1)
// 错误的示范
if (somecall() == -1) {
  printf("somecall() failed\n");
  if (errno == ...) { ... }
}

// 规范的使用,因为errno可能会被printf所改变,所以需要在somecall()之后将errno保存下来进行检查
if (somecall() == -1) {
  int errsv = errno;
  printf("somecall() failed\n");
  if (errsv == ...) { ... }
}
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    // 测试strerror函数
    errno = EACCES;
    fprintf(stderr, "EACCES: %s\n", strerror(errno));

    // 测试perror函数
    errno = ENOENT;
    perror(argv[0]);
    exit(EXIT_SUCCESS);
}

result:
EACCES: Permission denied
./1_8: No such file or directory
ENOMEM:Not enough space (POSIX.1),有时ENOMEM也是非致命性错误
EBUSY:Device or resource busy (POSIX.1),指明共享资源正在使用
EINTR:中断一个慢速系统调用(可能永远阻塞的系统调用,比如read、recv、select之类的)时,可以将它作为非致命性出错处理

用户标识

[root@localhost part_1]# id
uid=0(root) gid=0(root) groups=0(root)
[root@localhost part_1]# 
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    printf("uid = %d, gid = %d\n", getuid(), getgid());
    exit(EXIT_SUCCESS);
}

result:
// 用root用户去运行
uid = 0, gid = 0

// 用一般用户去运行
uid = 1000, gid = 1000

信号

这个我们在第10章详细讨论,这个主意的细节比较多

时间值

[root@localhost part_1]# cd /usr/include/
[root@localhost include]# time -p grep _POSIX_SOURCE */*.h > /dev/null 
real 0.02
user 0.00
sys 0.01
[root@localhost include]# 

系统调用和库函数

上一篇下一篇

猜你喜欢

热点阅读