本书介绍Linux环境下的编程方法,内容包括Linux系统命令、 Shell脚本、编程语言(gawk、Perl)、系统内核、安全体系、X Window等,内容丰富、论述全面,涵盖了Linux系统的方方面面。本书附带光盘包括了RedHat Linux系统的最新版本,及安装方法,还包括本书的大量程序代码,极大地方便了读者,为使用和将要使用Linux系统的技术人员提供了较全面的参考。
目 录
前言
第一篇 Linux系统介绍
第1章 Linux简介 …1
1.1 Linux 的起源 1
1.2 自由软件基金会的GNU计划 1
1.3 Linux 的发音 2
1.4 Linux 的特点 2
1.5 基本硬件要求 3
1.6 如何获得Linux 3
1.6.1 从网上下载Linux 3
1.6.2 从光盘获得Linux 3
1.7 涉及Linux 的Web 网址和新闻讨论组 6
1.8 Linux 的不足之处 7
第2章 外壳及常用命令 8
2.1 登录和退出 8
2.2 Linux 系统的外壳 8
2.3 外壳的常用命令 9
2.3.1 更改帐号密码 9
2.3.2 联机帮助 9
2.3.3 远程登录 9
2.3.4 文件或目录处理 9
2.3.5 改变工作目录 10
2.3.6 复制文件 10
2.3.7 移动或更改文件、目录名称 10
2.3.8 建立新目录 10
2.3.9 删除目录 11
2.3.10 删除文件 11
2.3.11 列出当前所在的目录位置 11
2.3.12 查看文件内容 11
2.3.13 分页查看文件内容 11
2.3.14 查看目录所占磁盘容量 11
2.3.15 文件传输 11
2.3.16 文件权限的设定 12
2.3.17 检查自己所属的工作组名称 13
2.3.18 改变文件或目录工作组所有权 13
2.3.19 改变文件或目录的最后修改时间 13
2.3.20 文件的链接 13
2.3.21 文件中字符串的查寻 14
2.3.22 查寻文件或命令的路径 14
2.3.23 比较文件或目录的内容 14
2.3.24 文件打印输出 14
2.3.25 一般文件的打印 14
2.3.26 troff 文件的打印 14
2.3.27 打印机控制命令 14
2.3.28 进程控制 15
2.3.29 外壳变量 16
2.3.30 环境变量 16
2.3.31 别名 16
2.3.32 历史命令 17
2.3.33 文件的压缩 17
2.3.34 管道命令的使用 17
2.3.35 输入/输出控制 18
2.3.36 查看系统中的用户 18
2.3.37 改变用户名 18
2.3.38 查看用户名 18
2.3.39 查看当前系统上所有工作站
的用户 19
2.3.40 与某工作站上的用户交谈 19
2.3.41 检查远程系统是否正常 19
2.3.42 电子邮件的使用简介 19
第3章 Linux系统的网络功能 21
3.1 Linux支持的网络协议 21
3.1.1 TCP/IP 21
3.1.2 TCP/IP 版本 6 21
3.1.3 IPX/SPX 21
3.1.4 AppleTalk 协议集 21
3.1.5 广域网 22
3.1.6 ISDN 22
3.1.7 PPP、SLIP及PLIP 22
3.1.8 业余无线电 22
3.1.9 ATM 22
3.2 Linux系统下的文件共享和打印共享 22
3.2.1 Machintosh 环境 22
3.2.2 Windows 环境 22
3.2.3 Novell 环境 23
3.2.4 UNIX 环境 23
3.3 Linux系统中的Internet/Intranet功能 23
3.3.1 邮件 23
3.3.2 Web 服务器 24
3.3.3 Web 浏览器 24
3.3.4 FTP 服务器和客户机 24
3.3.5 新闻服务 24
3.3.6 域名系统 24
3.3.7 DHCP和 bootp 24
3.3.8 NIS 24
3.4 Linux系统下应用程序的远程执行 24
3.4.1 Telnet 25
3.4.2 远程命令 25
3.4.3 X Window 25
3.5 Linux系统的网络互连功能 25
3.5.1 路由器 25
3.5.2 网桥 25
3.5.3 IP伪装 25
3.5.4 IP统计 26
3.5.5 IP 别名 26
3.5.6 流量限制器 26
3.5.7 防火墙 26
3.5.8 端口下传 26
3.5.9 负载平衡 26
3.5.10 EQL 27
3.5.11 代理服务器 27
3.5.12 按需拨号 27
3.5.13 管道、移动IP和虚拟个人网络 27
3.6 Linux系统中的网络管理 27
3.6.1 Linux系统下的网络管理应用程序 27
3.6.2 SNMP 28
3.7 企业级Linux网络 28
3.7.1 高可用性 28
3.7.2 RAID 28
3.7.3 冗余网络 28
第4章 Linux系统管理简介 29
4.1 root 帐号 29
4.2 启动和关闭系统 29
4.2.1 从软盘启动 29
4.2.2 使用LILO 启动 29
4.2.3 关闭Linux系统 30
4.3 挂接文件系统 30
4.3.1 挂接软盘 30
4.3.2 创建新的文件系统 30
4.3.3 卸载文件系统 31
4.4 检查文件系统 31
4.5 使用文件作为交换区 31
4.6 系统和文件的备份 32
4.7 设置系统 33
4.7.1 设置系统名 33
4.7.2 使用维护磁盘 33
4.7.3 重新设置root 帐号口令 33
4.7.4 设置登录信息 33
第二篇 Linux高级语言及管理编程
第5章 外壳编程 35
5.1 创建和运行外壳程序 35
5.1.1 创建外壳程序 35
5.1.2 运行外壳程序 35
5.2 使用外壳变量 36
5.2.1 给变量赋值 36
5.2.2 读取变量的值 37
5.2.3 位置变量和其他系统变量 37
5.2.4 引号的作用 37
5.3 数值运算命令 38
5.4 条件表达式 40
5.4.1 if 表达式 40
5.4.2 case 表达式 41
5.5 循环语句 42
5.5.1 for 语句 43
5.5.2 while 语句 43
5.5.3 until 语句 44
5.6 shift 命令 44
5.7 select 语句 45
5.8 repeat 语句 46
5.9 子函数 46
第6章 gawk语言编程 48
6.1 gawk的主要功能 48
6.2 如何执行gawk程序 48
6.3 文件、记录和字段 48
6.4 模式和动作 49
6.5 比较运算和数值运算 50
6.6 内部函数 50
6.6.1 随机数和数学函数 51
6.6.2 字符串的内部函数 51
6.6.3 输入输出的内部函数 52
6.7 字符串和数字 52
6.8 格式化输出 52
6.9 改变字段分隔符 54
6.10 元字符 54
6.11 调用gawk程序 55
6.12 BEGIN和END 55
6.13 变量 56
6.14 内置变量 56
6.15 控制结构 57
6.15.1 if 表达式 57
6.15.2 while 循环 57
6.15.3 for 循环 58
6.15.4 next 和 exit 58
6.16 数组 58
6.17 用户自定义函数 58
6.18 几个实例 59
第7章 Perl语言编程 60
7.1 什么是Perl 60
7.2 Perl的现状 60
7.3 初试Perl 60
7.4 Perl变量 60
7.4.1 标量 60
7.4.2 数组 63
7.4.3 相关数组 65
7.5 文件句柄和文件操作 65
7.6 循环结构 66
7.6.1 foreach循环 66
7.6.2 判断运算 66
7.6.3 for循环 67
7.6.4 while 和 until循环 67
7.7 条件结构 67
7.8 字符匹配 68
7.9 替换和翻译 69
7.9.1 替换 69
7.9.2 翻译 70
7.10 子过程 70
7.10.1 子过程的定义 70
7.10.2 参数 70
7.10.3 返回值 70
7.11 Perl程序的完整例子 71
第三篇 Linux系统内核分析
第8章 Linux内核简介 73
8.1 系统初始化 73
8.2 系统运行 73
8.3 内核提供的各种系统调用 74
8.3.1 进程的基本概念和系统
的基本数据结构 74
8.3.2 创建和撤消进程 74
8.3.3 执行程序 74
8.4 存取文件系统 75
第9章 系统进程 76
9.1 什么是进程 76
9.2 进程的结构 76
9.3 进程调度 78
9.4 进程使用的文件 79
9.5 进程使用的虚拟内存 80
9.6 创建进程 81
9.7 进程的时间和计时器 81
9.7.1 实时时钟 81
9.7.2 虚拟时钟 81
9.7.3 形象时钟 81
9.8 程序的执行 82
9.8.1 ELF文件 82
9.8.2 脚本文件 82
第10章 内存管理 83
10.1 内存管理的作用 83
10.2 虚拟内存的抽象模型 83
10.3 按需装入页面 84
10.4 交换 85
10.5 共享虚拟内存 85
10.6 存取控制 85
10.7 高速缓存 86
10.7.1 缓冲区高速缓存 86
10.7.2 页面高速缓存 86
10.7.3 交换高速缓存 86
10.7.4 硬件高速缓存 86
10.8 系统页面表 86
10.9 页面的分配和释放 87
10.9.1 页面的分配 88
10.9.2 页面的释放 88
10.10 内存映射 88
10.11 请求调页 89
10.12 页面高速缓存 89
10.13 内核交换守护进程 90
第11章 进程间通信 91
11.1 信号机制 91
11.2 管道机制 92
11.3 System V IPC 机制 93
11.3.1 信息队列 93
11.3.2 信号量 94
11.3.3 共享内存 96
第12章 PCI 98
12.1 PCI 系统 98
12.2 PCI地址空间 98
12.3 PCI设置头 99
12.4 PCI I/O 和 PCI 内存地址 100
12.5 PCI-ISA桥 100
12.6 PCI-PCI 桥 100
12.7 PCI初始化 101
12.7.1 Linux系统内核有关PCI的
数据结构 101
12.7.2 PCI 设备驱动程序 102
12.7.3 PCI BIOS 函数 105
12.7.4 PCI Fixup 105
第13章 中断和中断处理 106
13.1 中断 106
13.2 可编程中断控制器 106
13.3 初始化中断处理的数据结构 107
13.4 中断处理 108
第14章 设备驱动程序 109
14.1 硬件设备的管理 109
14.2 轮询和中断 110
14.3 直接内存存取 110
14.4 内存 111
14.5 设备驱动程序和内核之间的接口 111
14.5.1 字符设备 112
14.5.2 块设备 113
14.6 硬盘 113
14.6.1 IDE 硬盘 115
14.6.2 初始化IDE 硬盘子系统 115
14.6.3 SCSI 硬盘 115
14.6.4 初始化 SCSI 磁盘子系统 116
14.6.5 传递块设备请求 118
14.7 网络设备 118
14.7.1 网络设备文件名 118
14.7.2 总线信息 118
14.7.3 网络接口标记 119
14.7.4 协议信息 119
14.7.5 初始化网络设备 119
第15章 文件系统 121
15.1 Linux文件系统概述 121
15.2 ext2文件系统 122
15.2.1 ext2的索引节点 122
15.2.2 ext2超级块 124
15.2.3 ext2 数据块组描述符 124
15.2.4 ext2 中的目录 125
15.2.5 在ext2 文件系统中查找文件 125
15.2.6 改变ext2 文件系统中文件
的大小 126
15.3 VFS 127
15.3.1 VFS 超级块 128
15.3.2 VFS 索引节点 129
15.3.3 登记文件系统 129
15.3.4 挂接文件系统 130
15.3.5 在VFS中查找文件 131
15.3.6 撤消文件系统 131
15.3.7 VFS 索引节点缓存 132
15.3.8 VFS目录缓存 132
15.4 缓冲区缓存 133
15.5 /proc 文件系统 135
第16章 网络系统 136
16.1 TCP/IP 网络简介 136
16.2 TCP/IP网络的分层 137
16.3 BSD 套接口 138
16.4 INET套接口层 140
16.4.1 创建BSD 套接口 141
16.4.2 给INET BSD 套接口指定地址 141
16.4.3 在INET BSD套接口上创建连接 142
16.4.4 监听INET BSD 套接口 142
16.4.5 接收连接请求 143
16.5 IP 层 143
16.5.1 套接口缓冲区 143
16.5.2 接收IP数据包 144
16.5.3 发送IP数据包 144
16.5.4 数据碎片 144
16.6 地址解析协议 145
第17章 系统内核机制 147
17.1 Bottom Half处理 147
17.2 任务队列 148
17.3 计时器 149
17.4 等待队列 149
17.5 信号量 150
第四篇 Linux系统高级编程
第18章 Linux内核模块编程 151
18.1 一个简单程序Hello World 151
18.2 设备文件 152
18.3 /proc文件系统 156
18.4 使用/proc输入 158
18.5 与设备文件通信 162
18.6 启动参数 169
18.7 系统调用 170
18.8 阻塞进程 172
18.9 替换printk 177
18.10 调度任务 178
第19章 有关进程通信的编程 181
19.1 进程间通信简介 181
19.2 半双工UNIX管道 181
19.2.1 基本概念 181
19.2.2 使用C语言创建管道 182
19.2.3 创建管道的简单方法 185
19.2.4 使用管道的自动操作 187
19.2.5 使用半双工管道时的注意事项 188
19.3 命名管道 188
19.3.1 基本概念 188
19.3.2 创建FIFO 188
19.3.3 FIFO操作 189
19.3.4 FIFO的阻塞 190
19.3.5 SIGPIPE信号 190
19.4 System V IPC 190
19.4.1 基本概念 190
19.4.2 消息队列基本概念 191
19.4.3 系统调用msgget() 194
19.4.4 系统调用msgsnd() 195
19.4.5 系统调用msgctl() 197
19.4.6 一个msgtool的实例 199
19.5 使用信号量编程 201
19.5.1 基本概念 201
19.5.2 系统调用semget() 202
19.5.3 系统调用semop() 203
19.5.4 系统调用semctl() 204
19.5.5 使用信号量集的实例:semtool 205
19.6 共享内存 209
19.6.1 基本概念 209
19.6.2 系统内部用户数据结构
shmid_ds 209
19.6.3 系统调用shmget() 210
19.6.4 系统调用shmat() 211
19.6.5 系统调用shmctl() 211
19.6.6 系统调用shmdt() 212
19.6.7 使用共享内存的实例:shmtool 212
第20章 高级线程编程 215
20.1 线程的概念和用途 215
20.2 一个简单的例子 215
20.3 线程同步 217
20.4 使用信号量协调程序 218
20.5 信号量的实现 220
20.5.1 Semaphore.h 220
20.5.2 Semaphore.c 221
第21章 Linux系统网络编程 225
21.1 什么是套接口 225
21.2 两种类型的Internet套接口 225
21.3 网络协议分层 225
21.4 数据结构 225
21.5 IP地址和如何使用IP地址 226
21.5.1 socket() 226
21.5.2 bind() 226
21.5.3 connect() 227
21.5.4 listen() 228
21.5.5 accept() 228
21.5.6 send() 和 recv() 229
21.5.7 sendto() 和 recvfrom() 230
21.5.8 close() 和 shutdown() 230
21.5.9 getpeername() 231
21.5.10 gethostname() 231
21.6 DNS 231
21.7 客户机/服务器模式 232
21.8 简单的数据流服务器程序 232
21.9 简单的数据流客户机程序 234
21.10 数据报套接口 235
21.11 阻塞 237
第22章 Linux I/O端口编程 240
22.1 如何在 C 语言下使用I/O端口 240
22.1.1 一般的方法 240
22.1.2 另一个替代方法: /dev/port 241
22.2 硬件中断 与 DMA 存取 241
22.3 高精确的时间 241
22.3.1 延迟时间 241
22.3.2 时间的量测 243
22.4 使用其他程序语言 243
22.5 一些有用的 I/O 端口 243
22.5.1 并行端口 243
22.5.2 游戏端口 244
22.5.3 串行端口 245
第五篇 Linux系统安全分析
第23章 系统管理员安全 247
23.1 安全管理 247
23.2 超级用户 247
23.3 文件系统安全 247
23.3.1 Linux文件系统概述 247
23.3.2 设备文件 248
23.3.3 /etc/mknod命令 249
23.3.4 安全考虑 249
23.3.5 find命令 250
23.3.6 secure程序 250
23.3.7 ncheck命令 250
23.3.8 安装和拆卸文件系统 250
23.3.9 系统目录和文件 251
23.4 作为root运行的程序 251
23.4.1 启动系统 251
23.4.2 init进程 251
23.4.3 进入多用户 252
23.4.4 shutdown命令 252
23.4.5 系统V的cron程序 252
23.4.6 系统V版本2之后的cron程序 252
23.4.7 /etc/profile 253
23.5 /etc/passwd文件 253
23.5.1 口令时效 253
23.5.2 UID和GID 254
23.6 /etc/group文件 254
23.7 增加、删除和移走用户 254
23.7.1 增加用户 254
23.7.2 删除用户 255
23.7.3 将用户移到另一个系统 255
23.8 安全检查 255
23.8.1 记帐 255
23.8.2 其他检查命令 256
23.8.3 安全检查程序的问题 256
23.8.4 系统泄密后怎么办 257
23.9 加限制的环境 258
23.9.1 加限制的外壳 258
23.9.2 用chroot()限制用户 258
23.10 小系统安全 259
23.11 物理安全 259
23.12 用户意识 260
23.13 系统管理员意识 261
23.13.1 保持系统管理员个人的
登录安全 261
23.13.2 保持系统安全 261
第24章 系统程序员安全 263
24.1 系统子程序 263
24.1.1 I/O子程序 263
24.1.2 进程控制 263
24.1.3 文件属性 264
24.1.4 UID和GID的处理 265
24.2 标准C程序库 265
24.2.1 标准I/O 265
24.2.2 /etc/passwd的处理 266
24.2.3 /etc/group的处理 267
24.2.4 加密子程序 268
24.2.5 运行外壳 268
24.3 编写安全的C程序 268
24.3.1 需要考虑的安全问题 268
24.3.2 SUID/SGID程序指导准则 269
24.3.3 编译、安装SUID/SGID程序
的方法 269
24.4 root用户程序的设计 270
第25章 Linux系统的网络安全 272
25.1 UUCP系统概述 272
25.1.1 UUCP命令 272
25.1.2 uux命令 272
25.1.3 uucico程序 273
25.1.4 uuxqt程序 273
25.2 UUCP的安全问题 273
25.2.1 USERFILE文件 273
25.2.2 L.cmds文件 274
25.2.3 uucp登录 274
25.2.4 uucp使用的文件和目录 274
25.3 HONEYDANBER UUCP 275
25.3.1 HONEYDANBER UUCP与
老UUCP的差别 275
25.3.2 登录名规则 276
25.3.3 MACHINE规则 277
25.3.4 组合MACHINE和LOGNAME
规则 278
25.3.5 uucheck命令 278
25.3.6 网关 278
25.3.7 登录文件检查 279
25.4 其他网络 279
25.4.1 远程作业登录 279
25.4.2 NSC网络系统 280
25.5 通信安全 280
25.5.1 物理安全 280
25.5.2 加密 281
25.5.3 用户身份鉴别 282
25.6 SUN OS系统的网络安全 283
25.6.1 确保NFS的安全 283
25.6.2 NFS安全性方面的缺陷 284
25.6.3 远程过程调用鉴别 284
25.6.4 Linux鉴别机制 284
25.6.5 DES鉴别系统 285
25.6.6 公共关键字的编码 286
25.6.7 网络实体的命名 286
25.6.8 DES鉴别系统的应用 287
25.6.9 遗留的安全问题 287
25.6.10 性能 288
25.6.11 启动和setuid程序引起的问题 288
25.6.12 小结 289
第26章 Linux系统的用户安全性 290
26.1 口令安全 290
26.2 文件许可权 290
26.3 目录许可 291
26.4 umask命令 291
26.5 设置用户ID和同组用户ID许可 291
26.6 cp mv ln和cpio命令 291
26.7 su和newgrp命令 292
26.7.1 su命令 292
26.7.2 newgrp命令 292
26.8 文件加密 292
26.9 其他安全问题 293
26.9.1 用户的.profile文件 293
26.9.2 ls -a 293
26.9.3 .exrc文件 293
26.9.4 暂存文件和目录 293
26.9.5 UUCP和其他网络 293
26.9.6 特洛伊木马 294
26.9.7 诱骗 294
26.9.8 计算机病毒 294
26.9.9 要离开自己已登录的终端 294
26.9.10 智能终端 294
26.9.11 断开与系统的连接 294
26.9.12 cu命令 295
26.10 保持帐户安全的要点 295
第六篇 X window系统的内部结构和使用
第27章 X Window系统的基本知识 297
27.1 X Window系统介绍 297
27.1.1 X的特点 297
27.1.2 什么是窗口系统 298
27.1.3 X发展的历史 299
27.1.4 X的产品 299
27.1.5 MIT发行的X 299
27.2 X的基本结构 302
27.2.1 X 的基本元素 303
27.2.2 服务程序和客户程序如何
交互通信 304
27.2.3 X 的网络概况 306
27.3 从用户界面的角度概观X 307
27.3.1 管理界面:窗口管理器 307
27.3.2 应用程序界面和工具箱 309
27.3.3 其他系统角度 309
27.4 术语和符号 310
27.4.1 术语 310
27.4.2 符号 311
27.5 启动和关闭X 312
27.5.1 启动X 312
27.5.2 执行X程序的方式 313
27.5.3 关闭X 314
27.6 窗口管理器基础—uwm 315
27.6.1 什么是窗口管理器 315
27.6.2 启动uwm 315
27.6.3 基本窗口操作 —uwm
的菜单 315
27.6.4 移动窗口 316
27.6.5 重定窗口大小 316
27.6.6 建立新窗口 316
27.6.7 管理屏幕空间 318
27.6.8 中止应用程序窗口 320
27.6.9 激活uwm菜单的其他方式 320
27.7 使用 x的网络设备 320
27.7.1 指定远程终端机—display
选项 321
27.7.2 实际使用远程的显示器 322
27.7.3 控制存取显示器—xhost 322
27.8 终端机模拟器—详细介绍xterm 323
27.8.1 选择xterm功能—菜单与
命令行选项 323
27.8.2 滚动xterm屏幕 324
27.8.3 记录与终端机的交互过程—写
记录 325
27.8.4 剪贴文本 325
27.8.5 使用Tektronix模拟功能 326
27.8.6 使用不同的字体 327
27.8.7 使用颜色 327
27.8.8 其他xterm选项 327
27.8.9 设定终端机键盘 328
第28章 实用程序和工具 329
28.1 实用程序 329
28.2 保存、显示和打印屏幕图像 330
28.3 使用X的应用程序 332
28.3.1 文字编辑器—Xedit 333
28.3.2 邮件/信息处理系统—xmh 336
28.4 示例和游戏程序 336
28.4.1 找出通过随机迷宫的
路径—maze 336
28.4.2 担任鼠标指针的大眼睛—
xeyes 336
28.4.3 智慧盘游戏—puzzle 337
28.4.4 打印一个大X标志—xlogo 337
28.4.5 跳动的多面体—ico 337
28.4.6 动态几何图案—muncher与
plaid 337
28.7 显示信息和状态的程序 337
28.7.1 列出X服务程序的特征—
xdpyinfo 338
28.7.2 获取有关窗口的信息 338
28.7.3 观察X的事件—xev 340
第29章 定制X Window系统 341
29.1 使用X的字体和颜色 341
29.1.1 字体初步 341
29.1.2 字体命名 342
29.1.3 观察特定字体的内容—xfd 343
29.1.4 保存字体和位置 343
29.1.5 例子:在你的服务程序中
增加新字体 345
29.1.6 使用X的颜色 346
29.2 定义和使用图形 347
29.2.1 系统图形程序库 347
29.2.2 交互编辑图形—bitmap 347
29.2.3 编辑图形的其他方法 349
29.2.4 定制根窗口—xsetroot 349
29.3 定义应用程序的缺省选项—
Resources 350
29.3.1 什么是资源 350
29.3.2 XToolkit 351
29.3.3 管理资源—资源管理器 353
29.3.4 资源的类型—如何指定值 358
29.4 实际使用资源 359
29.4.1 在何处保存资源的缺省值 359
29.4.2 在服务程序上保存缺省值—
xrdb 363
29.4.3 常见的错误和修正 366
29.5 定制键盘和鼠标 367
29.5.1 实际使用转换 368
29.5.2 转换—格式和规则 374
29.5.3 转换规范中常见的问题 377
29.6 键盘和鼠标—对应和参数 379
29.6.1 键盘和鼠标映射—xmodmap 379
29.6.2 键盘和鼠标参数设定—xset 382
29.7 进一步介绍和定制uwm 384
29.7.1 uwm的新特征 384
29.7.2 定制uwm 386
29.8 显示器管理器—xdm 390
29.8.1 需要做些什么 390
29.8.2 xdm 391
29.8.3 xdm的更多信息 392
29.8.4 uwm配置 395
附录A Gcc使用介绍 396
附录B 安装X Window窗口系统 410