2016年5月

头条消息

今天看来是“安全日”,各种安全消息爆仓了。

前两天刚刚曝出的零日漏洞 ImageTragick 是对广泛使用的 ImageMagick 图片处理库中的一个严重攻击。而现在,CloudFlareSucuri 已经发现了利用该漏洞的真实攻击。 vBulletin 和 IP.Board 论坛是非常流行的论坛系统,很多网站都采用它们搭建在线论坛,而目前已经有针对这些程序发起的攻击了。相信在国内很快也会有针对 Discuz 论坛的攻击出现。

安全研究人员发现了一个名为 Enigma 的勒索软件,但是这个勒索软件是仅针对俄语用户的——所以非俄语用户可以偷着乐了:“We're Currently Safe”。笑哭了……

看起来这个世界充满了恶意,Adobe 刚刚宣布在 Flash 中发现了一个零日漏洞 CVE-2016-4117,而且,该漏洞已经被实际利用了进行攻击!这个漏洞影响到了运行在所有平台上的低于 21.0.0.226 版本的 Adobe Flash Player。

而且,据调查,1/4 的企业使用的过期的 IE,而只有 40% 的企业保持了 Flash Player 的更新。

不过,我们也有专门用于白帽子的 道德黑客工具 Ethical Hacking Tools 发行版:BlackArch Linux,在它刚刚发布的 BlackArch Linux 2016.04.28 版中,新增加了 80 个安全工具,已经有 1400 个之多的道德黑客工具!这里是工具列表,你可以看看!

版本更迭

  • Red Hat 发布了其 RHEL 6 的第八个维护版本,支持多达 300TB 的 XFS 文件系统。
  • 在经过三次延迟后,Fedora 24 终于发布了 Beta 版本。该版本带有 GNOME 3.20.1 桌面(默认只在工作站版本中)、最新的 GNU C 库 2.23 和 GCC 6,并使用了最新的 Linux 4.5.2 内核。当然,也解决了很多 Alpha 版本中的问题。正式版的 Fedora 预计在 6 月 14 日发布。
  • KDE Applications 16.04.1 和 KDE Plasma 5.6.4 发布,修复了若干问题。
  • Univention Corporate Server (UCS)4.1-2 发布,带来了几个重要的安全更新。

磁带设备应只用于定期的文件归档或将数据从一台服务器传送至另一台。通常磁带设备与 Unix 机器连接,用 mt 或 mtx 控制。强烈建议您将所有的数据同时备份到磁盘(也许是云中)和磁带设备中。在本教程中你将会了解到:

  • 磁带设备名
  • 管理磁带驱动器的基本命令
  • 基本的备份和恢复命令

为什么备份?

一个备份计划对定期备份文件来说很有必要,如果你宁愿选择不备份,那么丢失重要数据的风险会大大增加。有了备份,你就有了从磁盘故障中恢复的能力。备份还可以帮助你抵御:

  • 意外的文件删除
  • 文件或文件系统损坏
  • 服务器完全毁坏,包括由于火灾或其他问题导致的同盘备份毁坏
  • 硬盘或 SSD 崩溃
  • 病毒或勒索软件破坏或删除文件

你可以使用磁带归档备份整个服务器并将其离线存储。

理解磁带文件标记和块大小

Fig.01: Tape file marks

图01:磁带文件标记

每个磁带设备能存储多个备份文件。磁带备份文件通过 cpio,tar,dd 等命令创建。同时,磁带设备可以由多种程序打开、写入数据、及关闭。你可以存储若干备份(磁带文件)到一个物理磁带上。在每个磁带文件之间有个“磁带文件标记”。这用来指示一个物理磁带上磁带文件的结尾以及另一个文件的开始。你需要使用 mt 命令来定位磁带(快进,倒带和标记)。

磁带上的数据是如何存储的

Fig.02: How data is stored on a tape

图02:磁带上的数据是如何存储的

所有的数据使用 tar 以连续磁带存储格式连续地存储。第一个磁带归档会从磁带的物理开始端开始存储(tar #0)。接下来的就是 tar #1,以此类推。

Unix 上的磁带设备名

  1. /dev/rmt/0 或 /dev/rmt/1 或 /dev/rmt/[0-127] :Unix 上的常规磁带设备名。磁带自动倒回。
  2. /dev/rmt/0n :以无倒回为特征,换言之,磁带使用之后,停留在当前状态等待下个命令。
  3. /dev/rmt/0b :使用磁带接口,也就是 BSD 的行为。各种类型的操作系统比如 AIX,Windows,Linux,FreeBSD 等的行为更有可读性。
  4. /dev/rmt/0l :设置密度为低。
  5. /dev/rmt/0m :设置密度为中。
  6. /dev/rmt/0u :设置密度为高。
  7. /dev/rmt/0c :设置密度为压缩。
  8. /dev/st[0-9] :Linux 特定 SCSI 磁带设备名。
  9. /dev/sa[0-9] :FreeBSD 特定 SCSI 磁带设备名。
  10. /dev/esa0 :FreeBSD 特定 SCSI 磁带设备名,在关闭时弹出(如果可以的话)。

磁带设备名示例

  • /dev/rmt/1cn 指明正在使用 unity 1,压缩密度,无倒回。
  • /dev/rmt/0hb 指明正在使用 unity 0,高密度,BSD 行为。
  • Linux 上的自动倒回 SCSI 磁带设备名:/dev/st0
  • Linux 上的无倒回 SCSI 磁带设备名:/dev/nst0
  • FreeBSD 上的自动倒回 SCSI 磁带设备名:/dev/sa0
  • FreeBSD 上的无倒回 SCSI 磁带设备名:/dev/nsa0

如何列出已安装的 scsi 磁带设备?

输入下列命令:

### Linux(更多信息参阅 man) ###
lsscsi
lsscsi -g

### IBM AIX ###
lsdev -Cc tape
lsdev -Cc adsm
lscfg -vl rmt*

### Solaris Unix ###
cfgadm –a
cfgadm -al
luxadm probe
iostat -En

### HP-UX Unix ###
ioscan Cf
ioscan -funC tape
ioscan -fnC tape
ioscan -kfC tape

来自我的 Linux 服务器的输出示例:

Fig.03: Installed tape devices on Linux server

图03:Linux 服务器上已安装的磁带设备

mt 命令示例

在 Linux 和类 Unix 系统上,mt 命令用来控制磁带驱动器的操作,比如查看状态或查找磁带上的文件或写入磁带控制标记。下列大多数命令需要作为 root 用户执行。语法如下:

mt -f /tape/device/name operation

设置环境

你可以设置 TAPE shell 变量。这是磁带驱动器的路径名。在 FreeBSD 上默认的(如果变量没有设置,而不是 null)是 /dev/nsa0。可以通过 mt 命令的 -f 参数传递变量覆盖它,就像下面解释的那样。

 ### 添加到你的 shell 配置文件 ###
 TAPE=/dev/st1 #Linux
 TAPE=/dev/rmt/2 #Unix
 TAPE=/dev/nsa3 #FreeBSD
 export TAPE

1:显示磁带/驱动器状态

mt status  ### Use default
mt -f /dev/rmt/0  status ### Unix
mt -f /dev/st0 status ### Linux
mt -f /dev/nsa0 status ### FreeBSD
mt -f /dev/rmt/1 status ### Unix unity 1 也就是 tape device no. 1

你可以像下面一样使用 shell 循环语句遍历一个系统并定位其所有的磁带驱动器:

for d in 0 1 2 3 4 5
do
 mt -f "/dev/rmt/${d}" status
done

2:倒带

mt rew
mt rewind
mt -f /dev/mt/0 rewind
mt -f /dev/st0 rewind

3:弹出磁带

mt off
mt offline
mt eject
mt -f /dev/mt/0 off
mt -f /dev/st0 eject

4:擦除磁带(倒带,在支持的情况下卸载磁带)

mt erase
mt -f /dev/st0 erase  #Linux
mt -f /dev/rmt/0 erase #Unix

5:张紧磁带盒

如果磁带在读取时发生错误,你重新张紧磁带,清洁磁带驱动器,像下面这样再试一次:

mt retension
mt -f /dev/rmt/1 retension #Unix
mt -f /dev/st0 retension #Linux

6:在磁带当前位置写入 EOF 标记

mt eof
mt weof
mt -f /dev/st0 eof

7:将磁带前进指定的文件标记数目,即跳过指定个 EOF 标记

磁带定位在下一个文件的第一个块,即磁带会定位在下一区域的第一个块(见图01):

mt fsf
mt -f /dev/rmt/0 fsf
mt -f /dev/rmt/1 fsf 1 #go 1 forward file/tape (see fig.01)

8:将磁带后退指定的文件标记数目,即倒带指定个 EOF 标记

磁带定位在下一个文件的第一个块,即磁带会定位在 EOF 标记之后(见图01):

mt bsf
mt -f /dev/rmt/1 bsf
mt -f /dev/rmt/1 bsf 1 #go 1 backward file/tape (see fig.01)

这里是磁带定位命令列表:

   fsf    前进指定的文件标记数目。磁带定位在下一个文件的第一块。

   fsfm   前进指定的文件标记数目。磁带定位在前一文件的最后一块。

   bsf    后退指定的文件标记数目。磁带定位在前一文件的最后一块。

   bsfm   后退指定的文件标记数目。磁带定位在下一个文件的第一块。

   asf    磁带定位在指定文件标记数目的开始位置。定位通过先倒带,再前进指定的文件标记数目来实现。

   fsr    前进指定的记录数。

   bsr    后退指定的记录数。

   fss    (SCSI tapes)前进指定的 setmarks。

   bss    (SCSI tapes)后退指定的 setmarks。

基本备份命令

让我们来看看备份和恢复命令。

9:备份目录(tar 格式)

tar cvf /dev/rmt/0n /etc
tar cvf /dev/st0 /etc

10:恢复目录(tar 格式)

tar xvf /dev/rmt/0n -C /path/to/restore
tar xvf /dev/st0 -C /tmp

11:列出或检查磁带内容(tar 格式)

mt -f /dev/st0 rewind; dd if=/dev/st0 of=-

### tar 格式 ###
tar tvf {DEVICE} {Directory-FileName}
tar tvf /dev/st0
tar tvf /dev/st0 desktop
tar tvf /dev/rmt/0 foo > list.txt

12:使用 dump 或 ufsdump 备份分区

### Unix 备份 c0t0d0s2 分区 ###
ufsdump 0uf /dev/rmt/0  /dev/rdsk/c0t0d0s2

### Linux 备份 /home 分区 ###
dump 0uf /dev/nst0 /dev/sda5
dump 0uf /dev/nst0 /home

### FreeBSD 备份 /usr 分区 ###
dump -0aL -b64 -f /dev/nsa0 /usr

12:使用 ufsrestore 或 restore 恢复分区

### Unix ###
ufsrestore xf /dev/rmt/0
### Unix 交互式恢复 ###
ufsrestore if /dev/rmt/0

### Linux ###
restore rf /dev/nst0
### 从磁带媒介上的第6个备份交互式恢复 ###
restore isf 6 /dev/nst0

### FreeBSD 恢复 ufsdump 格式 ###
restore -i -f /dev/nsa0

13:从磁带开头开始写入(见图02)

### 这会覆盖磁带上的所有数据 ###
mt -f /dev/st1 rewind

### 备份 home ###
tar cvf /dev/st1 /home

### 离线并卸载磁带 ###
mt -f /dev/st0 offline

从磁带开头开始恢复:

mt -f /dev/st0 rewind
tar xvf /dev/st0
mt -f /dev/st0 offline

14:从最后一个 tar 后开始写入(见图02)

### 这会保留之前写入的数据 ###
mt -f /dev/st1 eom

### 备份 home ###
tar cvf /dev/st1 /home

### 卸载 ###
mt -f /dev/st0 offline

15:从 tar number 2 后开始写入(见图02)

### 在 tar number 2 之后写入(应该是 2+1)###
mt -f /dev/st0 asf 3
tar cvf /dev/st0 /usr

### asf 等效于 fsf ###
mt -f /dev/sf0 rewind
mt -f /dev/st0 fsf 2

从 tar number 2 恢复 tar:

mt -f /dev/st0 asf 3
tar xvf /dev/st0
mt -f /dev/st0 offline

如何验证使用 tar 创建的备份磁带?

定期做全系统修复和服务测试是很重要的,这是唯一确定整个系统正确工作的途径。参见我们的验证 tar 命令磁带备份的教程以获取更多信息。

示例 shell 脚本

#!/bin/bash
# A UNIX / Linux shell script to backup dirs to tape device like /dev/st0 (linux)
# This script make both full and incremental backups.
# You need at two sets of five  tapes. Label each tape as Mon, Tue, Wed, Thu and Fri.
# You can run script at midnight or early morning each day using cronjons.
# The operator or sys admin can replace the tape every day after the script has done.
# Script must run as root or configure permission via sudo.
# -------------------------------------------------------------------------
# Copyright (c) 1999 Vivek Gite <[email protected]>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------
# Last updated on : March-2003 - Added log file support.
# Last updated on : Feb-2007 - Added support for excluding files / dirs.
# -------------------------------------------------------------------------
LOGBASE=/root/backup/log

# Backup dirs; do not prefix /
BACKUP_ROOT_DIR="home sales"

# Get todays day like Mon, Tue and so on
NOW=$(date +"%a")

# Tape devie name
TAPE="/dev/st0"

# Exclude file
TAR_ARGS=""
EXCLUDE_CONF=/root/.backup.exclude.conf

# Backup Log file
LOGFIILE=$LOGBASE/$NOW.backup.log

# Path to binaries
TAR=/bin/tar
MT=/bin/mt
MKDIR=/bin/mkdir

# ------------------------------------------------------------------------
# Excluding files when using tar
# Create a file called $EXCLUDE_CONF using a text editor
# Add files matching patterns such as follows (regex allowed):
# home/vivek/iso
# home/vivek/*.cpp~
# ------------------------------------------------------------------------
[ -f $EXCLUDE_CONF ] && TAR_ARGS="-X $EXCLUDE_CONF"

#### Custom functions #####
# Make a full backup
full_backup(){
    local old=$(pwd)
    cd /
    $TAR $TAR_ARGS -cvpf $TAPE $BACKUP_ROOT_DIR
    $MT -f $TAPE rewind
    $MT -f $TAPE offline
    cd $old
}

# Make a  partial backup
partial_backup(){
    local old=$(pwd)
    cd /
    $TAR $TAR_ARGS -cvpf $TAPE -N "$(date -d '1 day ago')" $BACKUP_ROOT_DIR
    $MT -f $TAPE rewind
    $MT -f $TAPE offline
    cd $old
}

# Make sure all dirs exits
verify_backup_dirs(){
    local s=0
    for d in $BACKUP_ROOT_DIR
    do
        if [ ! -d /$d ];
        then
            echo "Error : /$d directory does not exits!"
            s=1
        fi
    done
    # if not; just die
    [ $s -eq 1 ] && exit 1
}

#### Main logic ####

# Make sure log dir exits
[ ! -d $LOGBASE ] && $MKDIR -p $LOGBASE

# Verify dirs
verify_backup_dirs

# Okay let us start backup procedure
# If it is Monday make a full backup;
# For Tue to Fri make a partial backup
# Weekend no backups
case $NOW in
    Mon)    full_backup;;
    Tue|Wed|Thu|Fri)    partial_backup;;
    *) ;;
esac > $LOGFIILE 2>&1

关于第三方备份工具

Linux 和类Unix系统都提供了许多第三方工具,可以用来安排备份,包括磁带备份在内,如:

  • Amanda
  • Bacula
  • rsync
  • duplicity
  • rsnapshot

另行参阅


via: http://www.cyberciti.biz/hardware/unix-linux-basic-tape-management-commands/

作者:Vivek Gite 译者:alim0x 校对:Mr小眼儿

本文由 LCTT 原创编译,Linux中国 荣誉推出

头条消息

在 Google 的 Play 市场中发现了一个名为 Viking Horde 的高危木马,它已经在五个应用中发现:Viking Jump、Parrot Copter、WiFi Plus、Memory Booster 和 Simple 2048。感染该木马的设备可以被攻击者利用来进行点击欺诈、发送短信甚至发起 DDoS 攻击。这些应用虽然已被 Google 清除,但是安全研究人员称,同样的手法可以绕过 Google 的应用审查过程,所以将来还有可能出现更多的含有该木马的应用。

版本更迭

  • AryaLinux 发布了 2016.04 版本。它是一个基于 LFS 及 BLFS 的发行版,采用了轻量级的 MATE 桌面。
  • Q4OS 项目发布了针对树莓派 3B 的版本, Q4OS 是一个轻巧易用的 Linux 系统,基于 Raspbian 构建,提供了已经优化好的 TDE (Trinity 桌面环境)。
  • Canonical 为 Ubuntu 12.04Ubuntu 14.04Ubuntu 15.10 修复了多个内核安全补丁。
  • Mesa 3D 图形库发布 11.1.4 ,但是建议用户升级到 11.2 系列,它也最新发布了 11.2.2 版本。
  • Solus 项目发布了新打造的软件管理器,界面看起来非常现代化。
  • 在经过了一年多的开发后, Rebellin Linux 3 发布了。它是一个基于 Debian 的发行版,带有两种桌面环境 GNOME 和 MATE 。
  • Linux AIO 发布了 Linux AIO Debian Live 8.4.0 和 Linux AIO Debian Live 7.10.0 的 Live 镜像,将这两个版本的不同分支分别打包到了两个单一的 ISO 镜像中。

Linux 内核中自己实现了双向链表,可以在 include/linux/list.h 找到定义。我们将会首先从双向链表数据结构开始介绍内核里的数据结构。为什么?因为它在内核里使用的很广泛,你只需要在 free-electrons.com 检索一下就知道了。

首先让我们看一下在 include/linux/types.h 里的主结构体:

struct list_head {
    struct list_head *next, *prev;
};

你可能注意到这和你以前见过的双向链表的实现方法是不同的。举个例子来说,在 glib 库里是这样实现的:

struct GList {
  gpointer data;
  GList *next;
  GList *prev;
};

通常来说一个链表结构会包含一个指向某个项目的指针。但是 Linux 内核中的链表实现并没有这样做。所以问题来了:链表在哪里保存数据呢?。实际上,内核里实现的链表是侵入式链表(Intrusive list)。侵入式链表并不在节点内保存数据-它的节点仅仅包含指向前后节点的指针,以及指向链表节点数据部分的指针——数据就是这样附加在链表上的。这就使得这个数据结构是通用的,使用起来就不需要考虑节点数据的类型了。

比如:

struct nmi_desc {
    spinlock_t lock;
    struct list_head head;
};

让我们看几个例子来理解一下在内核里是如何使用 list_head 的。如上所述,在内核里有很多很多不同的地方都用到了链表。我们来看一个在杂项字符驱动里面的使用的例子。在 drivers/char/misc.c 的杂项字符驱动 API 被用来编写处理小型硬件或虚拟设备的小驱动。这些驱动共享相同的主设备号:

#define MISC_MAJOR              10

但是都有各自不同的次设备号。比如:

ls -l /dev |  grep 10
crw-------   1 root root     10, 235 Mar 21 12:01 autofs
drwxr-xr-x  10 root root         200 Mar 21 12:01 cpu
crw-------   1 root root     10,  62 Mar 21 12:01 cpu_dma_latency
crw-------   1 root root     10, 203 Mar 21 12:01 cuse
drwxr-xr-x   2 root root         100 Mar 21 12:01 dri
crw-rw-rw-   1 root root     10, 229 Mar 21 12:01 fuse
crw-------   1 root root     10, 228 Mar 21 12:01 hpet
crw-------   1 root root     10, 183 Mar 21 12:01 hwrng
crw-rw----+  1 root kvm      10, 232 Mar 21 12:01 kvm
crw-rw----   1 root disk     10, 237 Mar 21 12:01 loop-control
crw-------   1 root root     10, 227 Mar 21 12:01 mcelog
crw-------   1 root root     10,  59 Mar 21 12:01 memory_bandwidth
crw-------   1 root root     10,  61 Mar 21 12:01 network_latency
crw-------   1 root root     10,  60 Mar 21 12:01 network_throughput
crw-r-----   1 root kmem     10, 144 Mar 21 12:01 nvram
brw-rw----   1 root disk      1,  10 Mar 21 12:01 ram10
crw--w----   1 root tty       4,  10 Mar 21 12:01 tty10
crw-rw----   1 root dialout   4,  74 Mar 21 12:01 ttyS10
crw-------   1 root root     10,  63 Mar 21 12:01 vga_arbiter
crw-------   1 root root     10, 137 Mar 21 12:01 vhci

现在让我们看看它是如何使用链表的。首先看一下结构体 miscdevice

struct miscdevice
{
      int minor;
      const char *name;
      const struct file_operations *fops;
      struct list_head list;
      struct device *parent;
      struct device *this_device;
      const char *nodename;
      mode_t mode;
};

可以看到结构体miscdevice的第四个变量list 是所有注册过的设备的链表。在源代码文件的开始可以看到这个链表的定义:

static LIST_HEAD(misc_list);

它实际上是对用list_head 类型定义的变量的扩展。

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

然后使用宏 LIST_HEAD_INIT 进行初始化,这会使用变量name 的地址来填充prevnext 结构体的两个变量。

#define LIST_HEAD_INIT(name) { &(name), &(name) }

现在来看看注册杂项设备的函数misc_register。它在一开始就用函数 INIT_LIST_HEAD 初始化了miscdevice->list

INIT_LIST_HEAD(&misc->list);

作用和宏LIST_HEAD_INIT一样。

static inline void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}

接下来,在函数device_create 创建了设备后,我们就用下面的语句将设备添加到设备链表:

list_add(&misc->list, &misc_list);

内核文件list.h 提供了向链表添加新项的 API 接口。我们来看看它的实现:

static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}

实际上就是使用3个指定的参数来调用了内部函数__list_add

  • new - 新项。
  • head - 新项将会插在head的后面
  • head->next - 插入前,head 后面的项。

__list_add的实现非常简单:

static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}

这里,我们在prevnext 之间添加了一个新项。所以我们开始时用宏LIST_HEAD_INIT定义的misc 链表会包含指向miscdevice->list 的向前指针和向后指针。

这儿还有一个问题:如何得到列表的内容呢?这里有一个特殊的宏:

#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

使用了三个参数:

  • ptr - 指向结构 list_head 的指针;
  • type - 结构体类型;
  • member - 在结构体内类型为list_head 的变量的名字;

比如说:

const struct miscdevice *p = list_entry(v, struct miscdevice, list)

然后我们就可以使用p->minor 或者 p->name来访问miscdevice。让我们来看看list_entry 的实现:

#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

如我们所见,它仅仅使用相同的参数调用了宏container_of。初看这个宏挺奇怪的:

#define container_of(ptr, type, member) ({                      \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

首先你可以注意到花括号内包含两个表达式。编译器会执行花括号内的全部语句,然后返回最后的表达式的值。

举个例子来说:

#include <stdio.h>

int main() {
    int i = 0;
    printf("i = %d\n", ({++i; ++i;}));
    return 0;
}

最终会打印出2

下一点就是typeof,它也很简单。就如你从名字所理解的,它仅仅返回了给定变量的类型。当我第一次看到宏container_of的实现时,让我觉得最奇怪的就是表达式((type *)0)中的0。实际上这个指针巧妙的计算了从结构体特定变量的偏移,这里的0刚好就是位宽里的零偏移。让我们看一个简单的例子:

#include <stdio.h>

struct s {
        int field1;
        char field2;
     char field3;
};

int main() {
    printf("%p\n", &((struct s*)0)->field3);
    return 0;
}

结果显示0x5

下一个宏offsetof会计算从结构体起始地址到某个给定结构字段的偏移。它的实现和上面类似:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

现在我们来总结一下宏container_of。只需给定结构体中list_head类型 字段的地址、名字和结构体容器的类型,它就可以返回结构体的起始地址。在宏定义的第一行,声明了一个指向结构体成员变量ptr的指针__mptr,并且把ptr 的地址赋给它。现在ptr__mptr 指向了同一个地址。从技术上讲我们并不需要这一行,但是它可以方便地进行类型检查。第一行保证了特定的结构体(参数type)包含成员变量member。第二行代码会用宏offsetof计算成员变量相对于结构体起始地址的偏移,然后从结构体的地址减去这个偏移,最后就得到了结构体。

当然了list_addlist_entry不是<linux/list.h>提供的唯一功能。双向链表的实现还提供了如下API:

  • list\_add
  • list\_add\_tail
  • list\_del
  • list\_replace
  • list\_move
  • list\_is\_last
  • list\_empty
  • list\_cut\_position
  • list\_splice
  • list\_for\_each
  • list\_for\_each\_entry

等等很多其它API。


via: https://github.com/0xAX/linux-insides/blob/master/DataStructures/dlist.md

译者:Ezio 校对:Mr小眼儿

本文由 LCTT 原创编译,Linux中国 荣誉推出

Ubuntu 在线峰会 2016 已经结束,我们之前已经报道过,Unity 8 和 Snap 将是 Ubuntu 桌面系统的未来

正如预期,Canonical 和 Ubuntu 的创始人 Mark Shuttleworth 在他的 Q&A 环节回答了用户各种关于 Ubuntu 和开源的问题。除了我们非常感兴趣的新的 Unity 8 界面之外,其它方面他并没有回答太多。

有一个看起来希望 Unity 8 能出现在 Ubuntu 16.10 的用户提问道,即将到来的 Unity 8 桌面环境在 Canonical 内部的优先级如何?Mark Shuttleworth 回答说 Unity 8 将默认安装到 Ubuntu 16.10——这事我们已经知道了。

在 Ubuntu 16.10 中,用户可以直接在登录屏选用 Unity 8 会话,而不需要按照那些复杂的教程,在命令行下运行一大堆命令来安装各种软件包和调整才能使用,就像用 KDE、MATE 或 GNOME 一样简单。

没有用户的首肯,Unity 8 不会取代 Unity 7

说到 Unity 8 在 Canonical 内的重要程度,Mark Shuttleworth 说有一个18个人的团队正在努力开发它,争取让一切都变得完善起来,这是他们现在最高优先级的事情。他也提到,Canonical 不会重复之前在 Ubuntu 11.04 中 Unity 7 上犯的同样错误

所以,最重要的是 Unity 8 不会成为用户的默认桌面,在没有用户反馈时就直接替代 Unity 7。这是一个非常好的消息。只有人们真正把 Unity 8 当成他们的桌面来用时,Canonical 才会完全移除 Unity 7 ,并用 Mir 上 Unity 8 去取代它。

Debian 开发者及 Linux 内核维护者 Ben Hutchings 在上周宣布,Debian 项目正在逐步停止对老式的 32 位 硬件架构的支持,32 位处理器里仅支持 i686 处理器。

在即将到来的 Debian GNU/Linux 9.0 “Stretch” 中,他们会停止支持 i586 和混合式 i586/i686 处理器。当前 Debian 9 正处于前期开发的 Debian Testing 通道。之所以停止支持,这是由于最近发布的 GCC 仅支持 i686 级别的处理器了

“可能你没有注意到这个变化, gcc for i386 现在被改成针对 i686 级别处理器的了,其生成的代码在 i686 之外的处理器上运行会崩溃。在这种老式系统上运行运行测试通道和不稳定通道的机器请切换到之前的稳定通道(Jessie)。” Ben Hutchings 在公告中说。

该变化已经出现在 Linux 内核 4.3 中,并在去年上传到了 Debian 不稳定通道的软件库中。现在,如果用户仍然在 i586 或 i486 的老式计算机上运行 Debian 的话,请切换到 Debian GNU/Linux 8 “Jessie”上。

在 Debian GNU/Linux 8 “Jessie” 上支持的处理器

当前 Debian GNU/Linux 的稳定版,并且也是长期支持的版本是 Jessie,即 Debian GNU/Linux 8,会直到 2020年前都提供安全补丁和软件更新的支持。也就是说,至少到 2018 年都会对老式处理器提供支持。

下列的处理器是 Debian 8 “Jessie”中支持,而在 Debian 9 “Stretch” 中不支持的:

AMD K5、K6、K6-2 (即 K6 3D)和 K6-3,DM&P/SiS Vortex86 和 Vortex86SX, Cyrix III, MediaGX, MediaGXm, IDT Winchip C6 和 Winchip 2, Intel Pentium 和 Pentium with MMX, Rise mP6, VIA C3 'Samuel 2' 和 C3 'Ezra' i386。