UNIX网络编程卷2进程间通信[笔记]

1 简介

1.1 什么是进程间通信?

IPC: Interprocess communication
是指运行在某个操作系统上的不同进程间各种消息传递的方式

1.2 线程

  1. 从IPC的角度来看,一个给定进程内的所有线程共享同样的全局变量
  2. 在支持线程的系统上,只有对空管道调用read的那个线程阻塞,同一进程的其余线程才能继续执行

1.3 IPC对象的持续性


  1. 自举的概念=加电自检+磁盘引导
  2. 对于一种给定形式的IPC,要求其具备随文件系统的持续性可能会使其性能降级,而IPC的一个基本设计目标是高性能

1.4 名字空间

对于除普通管道以外的所有形式的IPC来说,名字是客户与服务器彼此连接交换信息的手段。
(管道没有名字因此不能用于无亲缘关系的进程间,但是FIFO在一个文件系统中的路径名作为标识符因此可以用于无亲缘关系的进程间)

1.6 出错处理:包裹函数(wrapper function)

  1. 命名方法:将原有实际的函数名第一个字母改为大写。
  2. 作用:包裹函数执行实际的函数调用,测试其返回值,并在碰到错误时终止进程。旨在缩短程序长度(因为现实程序中,需要检查每个函数调用是否返回错误)
  3. 案例
1
2
3
4
5
6
7
8
9
// lib/wrapunix.c
void
Sem_post(sem_t *sem)
{
if (sem_post(sem) == -1)
{
err_sys("sem_post error");
}
}

Unix errno值

  1. 每当在一个Unix函数中发生错误时,全局变量errno将被设置称一个只是错误类型的正数(若函数不返回错误,则errno的值就无定义),函数本身则通常返回-1
  2. err_sys函数检查errno的值并输出相应的出错信息
  3. 所有正的错误值都是常值,具有E开头的全大写的名字(比如errno值为EAGAIN时,对应的出错消息为”Resource temporarily unavailable”),通常定义在头文件</usr/include/sys/errno.h>中,没有值为0的errno值
    [注意]Ubuntu中一般存放在/usr/include/asm-generic/errno.h
  4. 多线程环境下,每个线程必须有自己的errno变量

1.7 Unix标准

有关Unix标准化的大多数活动是由Posix和Open Group做的

Posix

Posix: Portable Operating System Interface 可移植操作系统接口; 1996年版的Posix.1标准的前言中声称ISO/IEC 9945由以下三部分组成

  1. 第一部分:系统应用程序接口(API)[C语言]
  2. 第二部分:Shell和实用程序
  3. 第三部分:系统管理
    第一二部分就是Posix.1和Posix.2

习题

  1. 图1-1展示了两个进程访问单个文件的情形。如果这两个进程都只是往该文件的末尾添加新的数据(譬如这是一个日志文件),那么需要什么类型的同步?

    答:这两个进程只需给open函数指定O_APPEND标志,或者给fopen函数指定添加模式。内核保证每次write都将新的数据添加到该文件的末尾。
  2. 查看你的系统[Ubuntu1804]中的头文件是如何定义errno变量的
    答:whereis errno.h查看位置得/usr/include/errno.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.

The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */

/*
* ISO C99 Standard: 7.5 Errors <errno.h>
*/

#ifndef _ERRNO_H
#define _ERRNO_H 1

#include <features.h>

/* The system-specific definitions of the E* constants, as macros. */
#include <bits/errno.h>

/* When included from assembly language, this header only provides the
E* constants. */
#ifndef __ASSEMBLER__

__BEGIN_DECLS

/* The error code set by various library functions. */
extern int *__errno_location (void) __THROW __attribute_const__;
# define errno (*__errno_location ())

# ifdef __USE_GNU

/* The full and simple forms of the name with which the program was
invoked. These variables are set up automatically at startup based on
the value of argv[0]. */
extern char *program_invocation_name;
extern char *program_invocation_short_name;

/* bits/errno.h may have defined this type. If it didn't, provide a
fallback definition. */
# ifndef __error_t_defined
# define __error_t_defined 1
typedef int error_t;
# endif

# endif /* __USE_GNU */

__END_DECLS

#endif /* !__ASSEMBLER__ */
#endif /* errno.h */

2 Posix IPC

2.1 概述

2.2 IPC名字

Posix.1对IPC名字的要求

  1. 必须符合已有的路径名规则(必须最多由PATH_MAX个字节构成,包括结尾的空字节)
  2. 若以斜杠开头,则对这些函数的不同调用将访问同一个队列;若不以斜杠开头,则效果取决于实现
  3. 名字中额外的斜杠的解释由实现定义

Solaris 2.6

要求以斜杠开头,但不允许有另外的斜杠符

Digital Unix 4.0B

在文件系统中创建所指定的路径名

移植性问题

  1. 当我们指定首字符为斜杠的名字如/tmp.1234时,符合Posix和Solaris规则,但是Digital Unix会尝试创建这个文件,除非我们有在根目录中的写权限否则会导致尝试失败
  2. 当我们指定一个类似/tmp/test.1234这样的名字时,如果/tmp目录存在,且具备该目录的写权限(对于多数Unix系统来说是可以的),但是Solaris下会导致失败 [避免移植性问题]   方法一:将Posix IPC名字的#define行放在一个便于修改的头文件中,这样应用程序转移到另一个系统上时,只需要修改这个头文件   方法二:自己定义一个名为px_ipc_name的函数,它为定位Posix IPC名字而添加上正确的前缀目录
1
2
#include "unpipc.h"
char *pc_ipc_name(const cahr *name);


----------- 本文结束 -----------




0%