2019年5月

学习在 Linux 中进程是如何与其他进程进行同步的。

本篇是 Linux 下进程间通信(IPC)系列的第一篇文章。这个系列将使用 C 语言代码示例来阐明以下 IPC 机制:

  • 共享文件
  • 共享内存(使用信号量)
  • 管道(命名的或非命名的管道)
  • 消息队列
  • 套接字
  • 信号

在聚焦上面提到的共享文件和共享内存这两个机制之前,这篇文章将带你回顾一些核心的概念。

核心概念

进程是运行着的程序,每个进程都有着它自己的地址空间,这些空间由进程被允许访问的内存地址组成。进程有一个或多个执行线程,而线程是一系列执行指令的集合:单线程进程就只有一个线程,而多线程的进程则有多个线程。一个进程中的线程共享各种资源,特别是地址空间。另外,一个进程中的线程可以直接通过共享内存来进行通信,尽管某些现代语言(例如 Go)鼓励一种更有序的方式,例如使用线程安全的通道。当然对于不同的进程,默认情况下,它们能共享内存。

有多种方法启动之后要进行通信的进程,下面所举的例子中主要使用了下面的两种方法:

  • 一个终端被用来启动一个进程,另外一个不同的终端被用来启动另一个。
  • 在一个进程(父进程)中调用系统函数 fork,以此生发另一个进程(子进程)。

第一个例子采用了上面使用终端的方法。这些代码示例的 ZIP 压缩包可以从我的网站下载到。

共享文件

程序员对文件访问应该都已经很熟识了,包括许多坑(不存在的文件、文件权限损坏等等),这些问题困扰着程序对文件的使用。尽管如此,共享文件可能是最为基础的 IPC 机制了。考虑一下下面这样一个相对简单的例子,其中一个进程(生产者 producer)创建和写入一个文件,然后另一个进程(消费者 consumer)从这个相同的文件中进行读取:

          writes +-----------+ reads
producer-------->| disk file |<-------consumer
                 +-----------+

在使用这个 IPC 机制时最明显的挑战是竞争条件可能会发生:生产者和消费者可能恰好在同一时间访问该文件,从而使得输出结果不确定。为了避免竞争条件的发生,该文件在处于状态时必须以某种方式处于被锁状态,从而阻止在操作执行时和其他操作的冲突。在标准系统库中与锁相关的 API 可以被总结如下:

  • 生产者应该在写入文件时获得一个文件的排斥锁。一个排斥锁最多被一个进程所拥有。这样就可以排除掉竞争条件的发生,因为在锁被释放之前没有其他的进程可以访问这个文件。
  • 消费者应该在从文件中读取内容时得到至少一个共享锁。多个读取者可以同时保有一个共享锁,但是没有写入者可以获取到文件内容,甚至在当只有一个读取者保有一个共享锁时。

共享锁可以提升效率。假如一个进程只是读入一个文件的内容,而不去改变它的内容,就没有什么原因阻止其他进程来做同样的事。但如果需要写入内容,则很显然需要文件有排斥锁。

标准的 I/O 库中包含一个名为 fcntl 的实用函数,它可以被用来检查或者操作一个文件上的排斥锁和共享锁。该函数通过一个文件描述符(一个在进程中的非负整数值)来标记一个文件(在不同的进程中不同的文件描述符可能标记同一个物理文件)。对于文件的锁定, Linux 提供了名为 flock 的库函数,它是 fcntl 的一个精简包装。第一个例子中使用 fcntl 函数来暴露这些 API 细节。

示例 1. 生产者程序

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

#define FileName "data.dat"
#define DataString "Now is the winter of our discontent\nMade glorious summer by this sun of York\n"

void report_and_exit(const char* msg) {
  perror(msg);
  exit(-1); /* EXIT_FAILURE */
}

int main() {
  struct flock lock;
  lock.l_type = F_WRLCK;    /* read/write (exclusive versus shared) lock */
  lock.l_whence = SEEK_SET; /* base for seek offsets */
  lock.l_start = 0;         /* 1st byte in file */
  lock.l_len = 0;           /* 0 here means 'until EOF' */
  lock.l_pid = getpid();    /* process id */

  int fd; /* file descriptor to identify a file within a process */
  if ((fd = open(FileName, O_RDWR | O_CREAT, 0666)) < 0)  /* -1 signals an error */
    report_and_exit("open failed...");

  if (fcntl(fd, F_SETLK, &lock) < 0) /** F_SETLK doesn't block, F_SETLKW does **/
    report_and_exit("fcntl failed to get lock...");
  else {
    write(fd, DataString, strlen(DataString)); /* populate data file */
    fprintf(stderr, "Process %d has written to data file...\n", lock.l_pid);
  }

  /* Now release the lock explicitly. */
  lock.l_type = F_UNLCK;
  if (fcntl(fd, F_SETLK, &lock) < 0)
    report_and_exit("explicit unlocking failed...");

  close(fd); /* close the file: would unlock if needed */
  return 0;  /* terminating the process would unlock as well */
}

上面生产者程序的主要步骤可以总结如下:

  • 这个程序首先声明了一个类型为 struct flock 的变量,它代表一个锁,并对它的 5 个域做了初始化。第一个初始化
lock.l_type = F_WRLCK; /* exclusive lock */

使得这个锁为排斥锁(read-write)而不是一个共享锁(read-only)。假如生产者获得了这个锁,则其他的进程将不能够对文件做读或者写操作,直到生产者释放了这个锁,或者显式地调用 fcntl,又或者隐式地关闭这个文件。(当进程终止时,所有被它打开的文件都会被自动关闭,从而释放了锁)

  • 上面的程序接着初始化其他的域。主要的效果是整个文件都将被锁上。但是,有关锁的 API 允许特别指定的字节被上锁。例如,假如文件包含多个文本记录,则单个记录(或者甚至一个记录的一部分)可以被锁,而其余部分不被锁。
  • 第一次调用 fcntl
if (fcntl(fd, F_SETLK, &lock) < 0)

尝试排斥性地将文件锁住,并检查调用是否成功。一般来说, fcntl 函数返回 -1 (因此小于 0)意味着失败。第二个参数 F_SETLK 意味着 fcntl 的调用不是堵塞的;函数立即做返回,要么获得锁,要么显示失败了。假如替换地使用 F_SETLKW(末尾的 W 代指等待),那么对 fcntl 的调用将是阻塞的,直到有可能获得锁的时候。在调用 fcntl 函数时,它的第一个参数 fd 指的是文件描述符,第二个参数指定了将要采取的动作(在这个例子中,F_SETLK 指代设置锁),第三个参数为锁结构的地址(在本例中,指的是 &lock)。

  • 假如生产者获得了锁,这个程序将向文件写入两个文本记录。
  • 在向文件写入内容后,生产者改变锁结构中的 l_type 域为 unlock 值:
lock.l_type = F_UNLCK;

并调用 fcntl 来执行解锁操作。最后程序关闭了文件并退出。

示例 2. 消费者程序

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

#define FileName "data.dat"

void report_and_exit(const char* msg) {
  perror(msg);
  exit(-1); /* EXIT_FAILURE */
}

int main() {
  struct flock lock;
  lock.l_type = F_WRLCK;    /* read/write (exclusive) lock */
  lock.l_whence = SEEK_SET; /* base for seek offsets */
  lock.l_start = 0;         /* 1st byte in file */
  lock.l_len = 0;           /* 0 here means 'until EOF' */
  lock.l_pid = getpid();    /* process id */

  int fd; /* file descriptor to identify a file within a process */
  if ((fd = open(FileName, O_RDONLY)) < 0)  /* -1 signals an error */
    report_and_exit("open to read failed...");

  /* If the file is write-locked, we can't continue. */
  fcntl(fd, F_GETLK, &lock); /* sets lock.l_type to F_UNLCK if no write lock */
  if (lock.l_type != F_UNLCK)
    report_and_exit("file is still write locked...");

  lock.l_type = F_RDLCK; /* prevents any writing during the reading */
  if (fcntl(fd, F_SETLK, &lock) < 0)
    report_and_exit("can't get a read-only lock...");

  /* Read the bytes (they happen to be ASCII codes) one at a time. */
  int c; /* buffer for read bytes */
  while (read(fd, &c, 1) > 0)    /* 0 signals EOF */
    write(STDOUT_FILENO, &c, 1); /* write one byte to the standard output */

  /* Release the lock explicitly. */
  lock.l_type = F_UNLCK;
  if (fcntl(fd, F_SETLK, &lock) < 0)
    report_and_exit("explicit unlocking failed...");

  close(fd);
  return 0;
}

相比于锁的 API,消费者程序会相对复杂一点儿。特别的,消费者程序首先检查文件是否被排斥性的被锁,然后才尝试去获得一个共享锁。相关的代码为:

lock.l_type = F_WRLCK;
...
fcntl(fd, F_GETLK, &lock); /* sets lock.l_type to F_UNLCK if no write lock */
if (lock.l_type != F_UNLCK)
  report_and_exit("file is still write locked...");

fcntl 调用中的 F_GETLK 操作指定检查一个锁,在本例中,上面代码的声明中给了一个 F_WRLCK 的排斥锁。假如特指的锁不存在,那么 fcntl 调用将会自动地改变锁类型域为 F_UNLCK 以此来显示当前的状态。假如文件是排斥性地被锁,那么消费者将会终止。(一个更健壮的程序版本或许应该让消费者会儿,然后再尝试几次。)

假如当前文件没有被锁,那么消费者将尝试获取一个共享(read-only)锁(F_RDLCK)。为了缩短程序,fcntl 中的 F_GETLK 调用可以丢弃,因为假如其他进程已经保有一个读写锁,F_RDLCK 的调用就可能会失败。重新调用一个只读锁能够阻止其他进程向文件进行写的操作,但可以允许其他进程对文件进行读取。简而言之,共享锁可以被多个进程所保有。在获取了一个共享锁后,消费者程序将立即从文件中读取字节数据,然后在标准输出中打印这些字节的内容,接着释放锁,关闭文件并终止。

下面的 % 为命令行提示符,下面展示的是从相同终端开启这两个程序的输出:

% ./producer
Process 29255 has written to data file...

% ./consumer
Now is the winter of our discontent
Made glorious summer by this sun of York

在本次的代码示例中,通过 IPC 传输的数据是文本:它们来自莎士比亚的戏剧《理查三世》中的两行台词。然而,共享文件的内容还可以是纷繁复杂的,任意的字节数据(例如一个电影)都可以,这使得文件共享变成了一个非常灵活的 IPC 机制。但它的缺点是文件获取速度较慢,因为文件的获取涉及到读或者写。同往常一样,编程总是伴随着折中。下面的例子将通过共享内存来做 IPC,而不是通过共享文件,在性能上相应的有极大的提升。

共享内存

对于共享内存,Linux 系统提供了两类不同的 API:传统的 System V API 和更新一点的 POSIX API。在单个应用中,这些 API 不能混用。但是,POSIX 方式的一个坏处是它的特性仍在发展中,并且依赖于安装的内核版本,这非常影响代码的可移植性。例如,默认情况下,POSIX API 用内存映射文件来实现共享内存:对于一个共享的内存段,系统为相应的内容维护一个备份文件。在 POSIX 规范下共享内存可以被配置为不需要备份文件,但这可能会影响可移植性。我的例子中使用的是带有备份文件的 POSIX API,这既结合了内存获取的速度优势,又获得了文件存储的持久性。

下面的共享内存例子中包含两个程序,分别名为 memwritermemreader,并使用信号量来调整它们对共享内存的获取。在任何时候当共享内存进入一个写入者场景时,无论是多进程还是多线程,都有遇到基于内存的竞争条件的风险,所以,需要引入信号量来协调(同步)对共享内存的获取。

memwriter 程序应当在它自己所处的终端首先启动,然后 memreader 程序才可以在它自己所处的终端启动(在接着的十几秒内)。memreader 的输出如下:

This is the way the world ends...

在每个源程序的最上方注释部分都解释了在编译它们时需要添加的链接参数。

首先让我们复习一下信号量是如何作为一个同步机制工作的。一般的信号量也被叫做一个计数信号量,因为带有一个可以增加的值(通常初始化为 0)。考虑一家租用自行车的商店,在它的库存中有 100 辆自行车,还有一个供职员用于租赁的程序。每当一辆自行车被租出去,信号量就增加 1;当一辆自行车被还回来,信号量就减 1。在信号量的值为 100 之前都还可以进行租赁业务,但如果等于 100 时,就必须停止业务,直到至少有一辆自行车被还回来,从而信号量减为 99。

二元信号量是一个特例,它只有两个值:0 和 1。在这种情况下,信号量的表现为互斥量(一个互斥的构造)。下面的共享内存示例将把信号量用作互斥量。当信号量的值为 0 时,只有 memwriter 可以获取共享内存,在写操作完成后,这个进程将增加信号量的值,从而允许 memreader 来读取共享内存。

示例 3. memwriter 进程的源程序

/** Compilation: gcc -o memwriter memwriter.c -lrt -lpthread **/
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>
#include "shmem.h"

void report_and_exit(const char* msg) {
  perror(msg);
  exit(-1);
}

int main() {
  int fd = shm_open(BackingFile,      /* name from smem.h */
                    O_RDWR | O_CREAT, /* read/write, create if needed */
                    AccessPerms);     /* access permissions (0644) */
  if (fd < 0) report_and_exit("Can't open shared mem segment...");

  ftruncate(fd, ByteSize); /* get the bytes */

  caddr_t memptr = mmap(NULL,       /* let system pick where to put segment */
                        ByteSize,   /* how many bytes */
                        PROT_READ | PROT_WRITE, /* access protections */
                        MAP_SHARED, /* mapping visible to other processes */
                        fd,         /* file descriptor */
                        0);         /* offset: start at 1st byte */
  if ((caddr_t) -1  == memptr) report_and_exit("Can't get segment...");

  fprintf(stderr, "shared mem address: %p [0..%d]\n", memptr, ByteSize - 1);
  fprintf(stderr, "backing file:       /dev/shm%s\n", BackingFile );

  /* semaphore code to lock the shared mem */
  sem_t* semptr = sem_open(SemaphoreName, /* name */
                           O_CREAT,       /* create the semaphore */
                           AccessPerms,   /* protection perms */
                           0);            /* initial value */
  if (semptr == (void*) -1) report_and_exit("sem_open");

  strcpy(memptr, MemContents); /* copy some ASCII bytes to the segment */

  /* increment the semaphore so that memreader can read */
  if (sem_post(semptr) < 0) report_and_exit("sem_post");

  sleep(12); /* give reader a chance */

  /* clean up */
  munmap(memptr, ByteSize); /* unmap the storage */
  close(fd);
  sem_close(semptr);
  shm_unlink(BackingFile); /* unlink from the backing file */
  return 0;
}

下面是 memwritermemreader 程序如何通过共享内存来通信的一个总结:

  • 上面展示的 memwriter 程序调用 shm_open 函数来得到作为系统协调共享内存的备份文件的文件描述符。此时,并没有内存被分配。接下来调用的是令人误解的名为 ftruncate 的函数
ftruncate(fd, ByteSize); /* get the bytes */

它将分配 ByteSize 字节的内存,在该情况下,一般为大小适中的 512 字节。memwritermemreader 程序都只从共享内存中获取数据,而不是从备份文件。系统将负责共享内存和备份文件之间数据的同步。

  • 接着 memwriter 调用 mmap 函数:
caddr_t memptr = mmap(NULL, /* let system pick where to put segment */
                  ByteSize, /* how many bytes */
                  PROT_READ | PROT_WRITE, /* access protections */
                  MAP_SHARED, /* mapping visible to other processes */
                  fd, /* file descriptor */
                  0); /* offset: start at 1st byte */

来获得共享内存的指针。(memreader 也做一次类似的调用。) 指针类型 caddr_tc 开头,它代表 calloc,而这是动态初始化分配的内存为 0 的一个系统函数。memwriter 通过库函数 strcpy(字符串复制)来获取后续操作的 memptr

  • 到现在为止,memwriter 已经准备好进行写操作了,但首先它要创建一个信号量来确保共享内存的排斥性。假如 memwriter 正在执行写操作而同时 memreader 在执行读操作,则有可能出现竞争条件。假如调用 sem_open 成功了:
sem_t* semptr = sem_open(SemaphoreName, /* name */
                     O_CREAT, /* create the semaphore */
                     AccessPerms, /* protection perms */
                     0); /* initial value */

那么,接着写操作便可以执行。上面的 SemaphoreName(任意一个唯一的非空名称)用来在 memwritermemreader 识别信号量。初始值 0 将会传递给信号量的创建者,在这个例子中指的是 memwriter 赋予它执行操作的权利。

  • 在写操作完成后,memwriter* 通过调用sem\_post` 函数将信号量的值增加到 1:
if (sem_post(semptr) < 0) ..

增加信号了将释放互斥锁,使得 memreader 可以执行它的操作。为了更好地测量,memwriter 也将从它自己的地址空间中取消映射,

munmap(memptr, ByteSize); /* unmap the storage *

这将使得 memwriter 不能进一步地访问共享内存。

示例 4. memreader 进程的源代码

/** Compilation: gcc -o memreader memreader.c -lrt -lpthread **/
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>
#include "shmem.h"

void report_and_exit(const char* msg) {
  perror(msg);
  exit(-1);
}

int main() {
  int fd = shm_open(BackingFile, O_RDWR, AccessPerms);  /* empty to begin */
  if (fd < 0) report_and_exit("Can't get file descriptor...");

  /* get a pointer to memory */
  caddr_t memptr = mmap(NULL,       /* let system pick where to put segment */
                        ByteSize,   /* how many bytes */
                        PROT_READ | PROT_WRITE, /* access protections */
                        MAP_SHARED, /* mapping visible to other processes */
                        fd,         /* file descriptor */
                        0);         /* offset: start at 1st byte */
  if ((caddr_t) -1 == memptr) report_and_exit("Can't access segment...");

  /* create a semaphore for mutual exclusion */
  sem_t* semptr = sem_open(SemaphoreName, /* name */
                           O_CREAT,       /* create the semaphore */
                           AccessPerms,   /* protection perms */
                           0);            /* initial value */
  if (semptr == (void*) -1) report_and_exit("sem_open");

  /* use semaphore as a mutex (lock) by waiting for writer to increment it */
  if (!sem_wait(semptr)) { /* wait until semaphore != 0 */
    int i;
    for (i = 0; i < strlen(MemContents); i++)
      write(STDOUT_FILENO, memptr + i, 1); /* one byte at a time */
    sem_post(semptr);
  }

  /* cleanup */
  munmap(memptr, ByteSize);
  close(fd);
  sem_close(semptr);
  unlink(BackingFile);
  return 0;
}

memwritermemreader 程序中,共享内存的主要着重点都在 shm_openmmap 函数上:在成功时,第一个调用返回一个备份文件的文件描述符,而第二个调用则使用这个文件描述符从共享内存段中获取一个指针。它们对 shm_open 的调用都很相似,除了 memwriter 程序创建共享内存,而 `memreader 只获取这个已经创建的内存:

int fd = shm_open(BackingFile, O_RDWR | O_CREAT, AccessPerms); /* memwriter */
int fd = shm_open(BackingFile, O_RDWR, AccessPerms); /* memreader */

有了文件描述符,接着对 mmap 的调用就是类似的了:

caddr_t memptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

mmap 的第一个参数为 NULL,这意味着让系统自己决定在虚拟内存地址的哪个地方分配内存,当然也可以指定一个地址(但很有技巧性)。MAP_SHARED 标志着被分配的内存在进程中是共享的,最后一个参数(在这个例子中为 0 ) 意味着共享内存的偏移量应该为第一个字节。size 参数特别指定了将要分配的字节数目(在这个例子中是 512);另外的保护参数(AccessPerms)暗示着共享内存是可读可写的。

memwriter 程序执行成功后,系统将创建并维护备份文件,在我的系统中,该文件为 /dev/shm/shMemEx,其中的 shMemEx 是我为共享存储命名的(在头文件 shmem.h 中给定)。在当前版本的 memwritermemreader 程序中,下面的语句

shm_unlink(BackingFile); /* removes backing file */

将会移除备份文件。假如没有 unlink 这个语句,则备份文件在程序终止后仍然持久地保存着。

memreadermemwriter 一样,在调用 sem_open 函数时,通过信号量的名字来获取信号量。但 memreader 随后将进入等待状态,直到 memwriter 将初始值为 0 的信号量的值增加。

if (!sem_wait(semptr)) { /* wait until semaphore != 0 */

一旦等待结束,memreader 将从共享内存中读取 ASCII 数据,然后做些清理工作并终止。

共享内存 API 包括显式地同步共享内存段和备份文件。在这次的示例中,这些操作都被省略了,以免文章显得杂乱,好让我们专注于内存共享和信号量的代码。

即便在信号量代码被移除的情况下,memwritermemreader 程序很大几率也能够正常执行而不会引入竞争条件:memwriter 创建了共享内存段,然后立即向它写入;memreader 不能访问共享内存,直到共享内存段被创建好。然而,当一个写操作处于混合状态时,最佳实践需要共享内存被同步。信号量 API 足够重要,值得在代码示例中着重强调。

总结

上面共享文件和共享内存的例子展示了进程是怎样通过共享存储来进行通信的,前者通过文件而后者通过内存块。这两种方法的 API 相对来说都很直接。这两种方法有什么共同的缺点吗?现代的应用经常需要处理流数据,而且是非常大规模的数据流。共享文件或者共享内存的方法都不能很好地处理大规模的流数据。按照类型使用管道会更加合适一些。所以这个系列的第二部分将会介绍管道和消息队列,同样的,我们将使用 C 语言写的代码示例来辅助讲解。


via: https://opensource.com/article/19/4/interprocess-communication-linux-storage

作者:Marty Kalin 选题:lujun9972 译者:FSSlc 校对:wxy

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

网络犯罪组织会为了争夺客户而相互竞争,会花重金招募最优秀的项目经理,甚至会寻找合适的人才来担任类似于首席执行官的角色,在规范管理人员配置和攻击事务之外负责如何帮助牟取更多的资金。来自IBM和谷歌的安全研究人员描述了网络犯罪组织内部是如何运作的,并且称它们经常会公司化运作。

IBM Security 威胁情报主管 Caleb Barlow 表示:“我们观察到他们也有比较严明的纪律,在办公时间里很活跃,他们也会在周末休息,他们也会定时工作,他们也会休假。它们会以公司化进行运作,会有一个老板全权管理所有攻击行为。它们就像是你雇佣装修公司一样,它们有着很多的分包商,就像是水电工、木工和油漆工一样,它们也和你一样正常上下班。”

Barlow 表示了解恶意黑客如何构建和运营其业务非常重要,而公司化可以更好地掌握他们正在攻击的任务。虽然并非所有网络犯罪组织都完全相同,但大体结构应该是这样的:领导者,例如 CEO,会监督整个组织的更广泛目标。而他或者她会雇佣和领导诸多“项目经理”,而每个项目经理负责每次网络攻击的不同部分。

恶意软件的攻击者可能首先购买或创建有针对性的攻击工具,以窃取集团所需的确切信息。另一位攻击者可能会发送欺诈性电子邮件,将恶意软件发送给目标公司。一旦软件成功交付,第三位攻击者可能会努力扩大集团在目标公司内的访问权限,并寻求可以在暗网上进行销售的相关信息。

IBM 还提供了一张信息图,展示了从犯罪集团的角度,如何发起为期 120 天针对一家财富 500 强公司的真实案例。负责 IBM X-Force 业务安全事件响应的 Christopher Scott 表示称在这种情况下,对财富 500 强企业的攻击意味着窃取和破坏数据,不同的颜色大致代表不同的工作职能。

在图形的左侧,专门破坏公司网络的攻击者以自己的方式进入业务以获得立足点。其他“项目经理”通过窃取他们的凭证来破坏各种员工帐户,并使用这些帐户执行该计划中的不同任务,从访问敏感区域或收集信息。时间线上的差距代表了黑客停止进行某些活动的时期,因此他们不会将公司用来检测犯罪活动的传感器干扰。

在 120 天周期尾声的时候,以鲜红色为代表的黑客专家最终画上句号,使用不同的恶意代码来破坏公司的各种数据。隶属于 Alphabet 集团“Other Bet”下方,专门从事网络安全的 Chronicle 公司研究主任 Juan Andres Guerrero-Saade 解释称:“如果我是一名优秀的开发人员,那么我会选择创建勒索软件并将其出售,或者将其像那些提供 software-as-a-service 的公司一样作为服务出售。然后我会不断维护这款恶意软件,如果你找到受害者并让他们受到感染支付赎金,那么我将收取 10% 或 20% 的分成。”

来源:cnBeta.COM

更多资讯

Mozilla 修复附加组件问题 同时警告用户不要尝试“可疑的解决方法”

Mozilla 今天推出了 Firefox 66.0.4,解决了因为证书问题导致的附加组件无法在 Firefox 浏览器中工作的问题。周五,过期的安全证书令全球的 Firefox 用户感到困惑,因为扩展被禁用并变得无法使用。Mozilla 现在发布了一个浏览器更新,并且“正在积极努力解决剩下的问题”。

来源: cnBeta.COM

详情: http://t.cn/EotsFEc

爱彼迎民宿路由器暗藏摄像头:官方回应已移除房源

5 月 5 日下午,有媒体报道称,在山东青岛一家爱彼迎(Airbnb)的民宿中,住客在无线路由器内发现了隐藏的摄像头和存储卡,拍摄方向正对卧室。5 日晚间,爱彼迎公关人员对此正式回应称,爱彼迎十分重视隐私保护,对任何侵犯隐私的行为都秉持零容忍态度,目前平台方已经永久性移除涉事房源。

来源: 快科技

详情: http://t.cn/Eocv7vE

来电显示暗藏黑色利益链 你的号码被“标注”了吗?

2015 年 8 月的一天,刘子倩用打车软件叫了一辆车,刚刚上车,他就被司机识破了身份。原来,司机手机上的一款来电号码识别软件,把刘子倩的身份信息标注为“记者”。当刘子倩拨通司机电话时,他的身份信息就已经泄露了。

来源: 法制日报
详情: http://t.cn/Eocvwx0

北京将实现水电气热大数据共享,严防数据丢失、泄露

《北京市公共数据管理办法》日前面向公众开征意见。记者获悉,北京将建设市、区两级大数据管理平台,目前已有11.5亿条数据在市级大数据管理平台汇聚。未来,对于无条件共享的数据,数据需求单位可通过市区两级大数据平台直接获取;对于有条件共享的数据,数据需求单位应根据提供单位的授权获取共享数据。

来源: 北京日报

详情: http://t.cn/EocvLOR

(信息来源于网络,安华金和搜集整理)

Ping Multiple Servers And Show The Output In Top-like Text UI

不久前,我们写了篇关于 fping 的文章,该程序能使我们能够同时 ping 多台主机。与传统的 ping 不同,fping 不会等待一台主机的超时。它使用循环法,这表示它将 ICMP Echo 请求发送到一台主机,然后转到另一台主机,最后一次显示哪些主机开启或关闭。今天,我们将讨论一个名为 pingtop 的类似程序。顾名思义,它会一次 ping 多台服务器,并在类似 top 的终端 UI 中显示结果。它是用 Python 写的自由开源程序。

安装 pingtop

可以使用 pip 安装 pingtoppip 是一个软件包管理器,用于安装用 Python 开发的程序。确保已在 Linux 中安装了 Python 3.7.x 和 pip。

要在 Linux 上安装 pip,请参阅以下链接。

安装 pip 后,运行以下命令安装 pingtop

$ pip install pingtop

现在让我们继续使用 pingtop ping 多个系统。

ping 多台服务器并在类似 top 的终端 UI 中显示

要 ping 多个主机/系统,请运行:

$ pingtop ostechnix.com google.com facebook.com twitter.com

现在,你将在一个漂亮的类似 top 的终端 UI 中看到结果,如下所示。

使用 pingtop ping 多台服务器

建议阅读:

我个人目前没有使用 pingtop 的情况。但我喜欢在这个在文本界面中展示 ping 命令输出的想法。试试看它,也许有帮助。

就是这些了。还有更多好东西。敬请期待!干杯!

资源:


via: https://www.ostechnix.com/ping-multiple-servers-and-show-the-output-in-top-like-text-ui/

作者:sk 选题:lujun9972 译者:geekpi 校对:wxy

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

正在寻找树莓派的替代品?这里有一些单板机可以满足你的 DIY 渴求。

树莓派是当前最流行的单板机。你可以在你的 DIY 项目中使用它,或者用它作为一个成本效益高的系统来学习编代码,或者为了你的便利,利用一个流媒体软件运行在上面作为流媒体设备。

你可以使用树莓派做很多事,但它不是各种极客的最终解决方案。一些人可能在寻找更便宜的开发板,一些可能在寻找更强大的。

无论是哪种情况,我们都有很多原因需要树莓派的替代品。因此,在这片文章里,我们将讨论最好的 12 个我们认为能够替代树莓派的单板机。

满足你 DIY 渴望的树莓派替代品

这个列表没有特定的顺序排名。链接的一部分是赞助链接。请阅读我们的赞助政策

1、Onion Omega2+

只要 $13,Omega2+ 是这里你可以找到的最便宜的 IoT 单板机设备。它运行 LEDE(Linux 嵌入式开发环境)Linux 系统 —— 这是一个基于 OpenWRT 的发行版。

由于运行一个自定义 Linux 系统,它的组成元件、花费和灵活性使它完美适合几乎所有类型的 IoT 应用。

你可以在亚马逊商城的 Onion Omega 套件或者从他们的网站下单,可能会收取额外的邮费。

关键参数:

  • MT7688 SoC
  • 2.4 GHz IEEE 802.11 b/g/n WiFi
  • 128 MB DDR2 RAM
  • 32 MB on-board flash storage
  • MicroSD Slot
  • USB 2.0
  • 12 GPIO Pins

查看官网

2、NVIDIA Jetson Nano Developer Kit

这是来自 NVIDIA 的只要 $99 的非常独特和有趣的树莓派替代品。是的,它不是每个人都能充分利用的设备 —— 只为特定的一组极客或者开发者而生。

NVIDIA 使用下面的用例解释它:

NVIDIA® Jetson Nano™ Developer Kit 是一个小的、强大的计算机,可以让你并行运行多个神经网络的应用像图像分类、对象侦察、图像分段、语音处理。全部在一个易于使用的、运行功率只有 5 瓦特的平台上。

nvidia

因此,基本上,如果你正在研究 AI 或者深度学习,你可以充分利用开发设备。如果你很好奇,该设备的产品计算模块将在 2019 年 7 月到来。

关键参数:

  • CPU: Quad-core ARM A57 @ 1.43 GHz
  • GPU: 128-core Maxwell
  • RAM: 4 GB 64-bit LPDDR4 25.6 GB/s
  • Display: HDMI 2.0
  • 4 x USB 3.0 and eDP 1.4

查看官网

3、ASUS Tinker Board S

ASUS Tinker Board S 不是大多数人可负担得起的树莓派的替换设备 ($82亚马逊商城),但是它是一个强大的替代品。它的特点是它有你通常可以发现与标准树莓派 3 一样的 40 针脚的连接器,但是提供了强大的处理器和 GPU。同样的,Tinker Board S 的大小恰巧和标准的树莓派3 一样大。

这个板子的主要亮点是 16 GB eMMC (用外行术语说,它的板上有一个类似 SSD 的存储单元使它工作时运行的更快。) 的存在。

关键参数:

  • Rockchip Quad-Core RK3288 processor
  • 2 GB DDR3 RAM
  • Integrated Graphics Processor
  • ARM® Mali™-T764 GPU
  • 16 GB eMMC
  • MicroSD Card Slot
  • 802.11 b/g/n, Bluetooth V4.0 + EDR
  • USB 2.0
  • 28 GPIO pins
  • HDMI Interface

查看网站

4、ClockworkPi

如果你正在想方设法组装一个模块化的复古的游戏控制台,Clockwork Pi 可能就是你需要的,它通常是 GameShell Kit 的一部分。然而,你可以 使用 $49 单独购买板子。

它紧凑的大小、WiFi 连接性和 micro HDMI 端口的存在使它成为许多方面的选择。

关键参数:

  • Allwinner R16-J Quad-core Cortex-A7 CPU @1.2GHz
  • Mali-400 MP2 GPU
  • RAM: 1GB DDR3
  • WiFi & Bluetooth v4.0
  • Micro HDMI output
  • MicroSD Card Slot

查看官网

5、Arduino Mega 2560

如果你正在研究机器人项目或者你想要一个 3D 打印机 —— Arduino Mega 2560 将是树莓派的便利的替代品。不像树莓派,它是基于微控制器而不是微处理器的。

在他们的官网,你需要花费 $38.50,或者在[在亚马逊商城是 $33](https://amzn.to/2KCi041)。

关键参数:

  • Microcontroller: ATmega2560
  • Clock Speed: 16 MHz
  • Digital I/O Pins: 54
  • Analog Input Pins: 16
  • Flash Memory: 256 KB of which 8 KB used by bootloader

查看官网

6、Rock64 Media Board

用与你可能想要的树莓派 3 B+ 相同的价格,你将在 Rock64 Media Board 上获得更快的处理器和双倍的内存。除此之外,如果你想要 1 GB RAM 版的,它提供了一个比树莓派更便宜的替代品,花费更少,只要 $10 。

不像树莓派,它没有无线连接支持,但是 USB 3.0 和 HDMI 2.0 的存在使它与众不同,如果它对你很重要的话。

关键参数:

  • Rockchip RK3328 Quad-Core ARM Cortex A53 64-Bit Processor
  • Supports up to 4GB 1600MHz LPDDR3 RAM
  • eMMC module socket
  • MicroSD Card slot
  • USB 3.0
  • HDMI 2.0

查看官网

7、Odroid-XU4

Odroid-XU4 是一个完美的树莓派的替代品,如果你有能够稍微提高预算的空间($80-$100 甚至更低,取决于存储的容量)。

它确实是一个强大的替代品并且体积更小。支持 eMMC 和 USB 3.0 使它工作起来更快。

关键参数:

  • Samsung Exynos 5422 Octa ARM Cortex™-A15 Quad 2Ghz and Cortex™-A7 Quad 1.3GHz CPUs
  • 2Gbyte LPDDR3 RAM
  • GPU: Mali-T628 MP6
  • USB 3.0
  • HDMI 1.4a
  • eMMC 5.0 module socket
  • MicroSD Card Slot

查看官网

8、PocketBeagle

它是一个难以置信的小的单板机 —— 几乎和树莓派Zero 相似。然而它的价格相当于完整大小的树莓派 3。主要的亮点是你可以用它作为一个 USB 便携式信息终端,并且进入 Linux 命令行工作。

关键参数:

  • Processor: Octavo Systems OSD3358 1GHz ARM® Cortex-A8
  • RAM: 512 MB DDR3
  • 72 expansion pin headers
  • microUSB
  • USB 2.0

查看官网

9、Le Potato

Libre Computer 出品的 Le Potato,其型号是 AML-S905X-CC。它需要花费你 $45

如果你花费的比树莓派更多的钱,你就能得到双倍内存和 HDMI 2.0 接口,这可能是一个完美的选择。尽管,你还是不能找到嵌入的无线连接。

关键参数:

  • Amlogic S905X SoC
  • 2GB DDR3 SDRAM
  • USB 2.0
  • HDMI 2.0
  • microUSB
  • MicroSD Card Slot
  • eMMC Interface

查看官网

10、Banana Pi M64

它自带了 8G 的 eMMC —— 这是替代树莓派的主要亮点。因此,它需要花费 $60。

HDMI 接口的存在使它胜任 4K。除此之外,Banana Pi 提供了更多种类的开源单板机作为树莓派的替代。

关键参数:

  • 1.2 Ghz Quad-Core ARM Cortex A53 64-Bit Processor-R18
  • 2GB DDR3 SDRAM
  • 8 GB eMMC
  • WiFi & Bluetooth
  • USB 2.0
  • HDMI

查看官网

11、Orange Pi Zero

Orange Pi Zero 相对于树莓派来说难以置信的便宜。你可以在 Aliexpress 或者亚马逊上以最多 $10 就能够获得。如果稍微多花点,你能够获得 512 MB RAM

如果这还不够,你可以花费大概 $25 获得更好的配置,比如 Orange Pi 3。

关键参数:

  • H2 Quad-core Cortex-A7
  • Mali400MP2 GPU
  • RAM: Up to 512 MB
  • TF Card support
  • WiFi
  • USB 2.0

查看官网

12、VIM 2 SBC by Khadas

由 Khadas 出品的 VIM 2 是最新的单板机,因此你能够在板上得到蓝牙 5.0 支持。它的价格范围从 $99 的基础款到上限 $140

基础款包含 2 GB RAM、16 GB eMMC 和蓝牙 4.1。然而,Pro/Max 版包含蓝牙 5.0,更多的内存,更多的 eMMC 存储。

关键参数:

  • Amlogic S912 1.5GHz 64-bit Octa-Core CPU
  • T820MP3 GPU
  • Up to 3 GB DDR4 RAM
  • Up to 64 GB eMMC
  • Bluetooth 5.0 (Pro/Max)
  • Bluetooth 4.1 (Basic)
  • HDMI 2.0a
  • WiFi

总结

我们知道有很多不同种类的单板机电脑。一些比树莓派更好 —— 它的一些小规格的版本有更便宜的价格。同样的,像 Jetson Nano 这样的单板机已经被裁剪用于特定用途。因此,取决于你需要什么 —— 你应该检查一下单板机的配置。

如果你知道比上述提到的更好的东西,请随意在下方评论来让我们知道。


via: https://itsfoss.com/raspberry-pi-alternatives/

作者:Ankush Das 选题:lujun9972 译者:warmfrog 校对:wxy

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

unikernel 是一种用于在云基础架构上部署应用程序的更小、更快、更安全的方式。使用 NanoVMs OPS,任何人都可以将 Linux 应用程序作为 unikernel 运行而无需额外编码。

Marcho Verch (CC BY 2.0)

随着 unikernel 的出现,构建和部署轻量级应用变得更容易、更可靠。虽然功能有限,但 unikernal 在速度和安全性方面有许多优势。

什么是 unikernel?

unikernel 是一种非常特殊的 单一地址空间 single-address-space 的机器镜像,类似于已经主导大批互联网的云应用,但它们相当小并且是单一用途的。它们很轻,只提供所需的资源。它们加载速度非常快,而且安全性更高 —— 攻击面非常有限。单个可执行文件中包含所需的所有驱动、I/O 例程和支持库。其最终生成的虚拟镜像可以无需其它部分就可以引导和运行。它们通常比容器快 10 到 20 倍。

潜在的攻击者无法进入 shell 并获得控制权,因为它没有 shell。他们无法获取系统的 /etc/passwd/etc/shadow 文件,因为这些文件不存在。创建一个 unikernel 就像应用将自己变成操作系统。使用 unikernel,应用和操作系统将成为一个单一的实体。你忽略了不需要的东西,从而消除了漏洞并大幅提高性能。

简而言之,unikernel:

  • 提供更高的安全性(例如,shell 破解代码无用武之地)
  • 比标准云应用占用更小空间
  • 经过高度优化
  • 启动非常快

unikernel 有什么缺点吗?

unikernel 的唯一严重缺点是你必须构建它们。对于许多开发人员来说,这是一个巨大的进步。由于应用的底层特性,将应用简化为所需的内容然后生成紧凑、平稳运行的应用可能很复杂。在过去,你几乎必须是系统开发人员或底层程序员才能生成它们。

这是怎么改变的?

最近(2019 年 3 月 24 日)NanoVMs 宣布了一个将任何 Linux 应用加载为 unikernel 的工具。使用 NanoVMs OPS,任何人都可以将 Linux 应用作为 unikernel 运行而无需额外编码。该应用还可以更快、更安全地运行,并且成本和开销更低。

什么是 NanoVMs OPS?

NanoVMs 是给开发人员的 unikernel 工具。它能让你运行各种企业级软件,但仍然可以非常严格地控制它的运行。

使用 OPS 的其他好处包括:

  • 无需经验或知识,开发人员就可以构建 unikernel。
  • 该工具可在笔记本电脑上本地构建和运行 unikernel。
  • 无需创建帐户,只需下载并一个命令即可执行 OPS。

NanoVMs 的介绍可以在 Youtube 上的 NanoVMs 视频 上找到。你还可以查看该公司的 LinkedIn 页面并在此处阅读有关 NanoVMs 安全性的信息。

还有有关如何入门的一些信息。


via: https://www.networkworld.com/article/3387299/how-to-quickly-deploy-run-linux-applications-as-unikernels.html

作者:Sandra Henry-Stocker 选题:lujun9972 译者:geekpi 校对:wxy

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

从国家互联网应急中心获悉,为了有效控制 WannaCry 勒索病毒的传播感染,国家互联网应急中心近日开通了该病毒感染数据免费查询服务。2017 年 5 月 12 日,WannaCry 勒索病毒利用 Windows SMB(“永恒之蓝”)漏洞在全球快速传播,造成全球计算机大范围感染。

国家互联网应急中心介绍说,为实时掌握 WannaCry 勒索病毒及其变种在我国的传播感染情况,国家互联网应急中心持续开展针对该病毒的监测工作。根据分析,WannaCry 勒索病毒成功感染计算机并运行后,首先会主动连接一个开关域名。如果与开关域名通信成功,该病毒将不运行勒索行为,但病毒文件仍驻留在被感染计算机中;如果通信失败,该病毒将运行勒索行为加密计算机中的文件,并继续向局域网或互联网上的其他计算机传播。

据悉,截至 2019 年 4 月 9 日,国家互联网应急中心监测发现我国境内疑似感染 WannaCry 勒索病毒的计算机数量超过 30 万台,仍有大量的计算机未安装“永恒之蓝”漏洞补丁和杀毒软件。我国计算机感染 WannaCry 勒索病毒疫情依然比较严峻。

为了有效控制 WannaCry 勒索病毒的传播感染,国家互联网应急中心开通了该病毒感染数据免费查询服务。查询说明如下:

1、WannaCry 勒索病毒暂只能感染 Windows 操作系统,请用户在 Windows 操作系统上的浏览器中输入查询地址打开查询页面进行查询,查询地址为:h ttp://wanna-check.cert.org.cn。

2、若提示 IP 地址承载的计算机受到感染,建议使用 WannaCry 勒索病毒专杀工具进行查杀,并及时修复相关漏洞。

3、如果使用宽带拨号上网或手机上网,由于 IP 地址经常变化,会导致查询结果不准确,仅供参考。

来源:快科技

更多资讯

中消协等发智能锁试验报告:半数存指纹识别安全风险

中国消费者协会、四川省保护消费者权益委员会、 深圳市消费者委员会、佛山市消费者委会今天联合发布智能门锁比较试验报告,29 款样品中,48.3% 的样品密码开启安全存在风险,50% 的样品指纹识别开启安全存在风险,85.7% 的样品信息识别卡开启安存在风险。

来源: 央视新闻客户端

详情: http://t.cn/EoLwr4r

如何让过期证书事故不再发生

证书过期是一种常见的问题,但其影响面却可能极其广泛。此类事故频繁发生是因为安装和更新证书是一个乏味的手动过程。证书过期的现象已经有了改善,Let’s Encrypt 和 SSLMate 等 CA 开始提供证书自动更新的方法。

来源: solidot.org

详情: http://t.cn/EoLwsEt

男子购买“教程”掌握点餐软件漏洞 边消费边退代金券大肆实施盗窃

如今,各大餐饮行业手机自助点餐软件兴起,特别是在快餐行业中,大大缓解了排队点餐的尴尬。但是由于软件程序中难免存在漏洞,也成为滋生犯罪的土壤。近日,徐汇区检察院对一起利用手机自助点餐软件漏洞,盗窃某知名快餐公司钱款的被告人钟某某提起公诉。

来源: 新民晚报

详情: http://t.cn/EoLAw0A

中国一智能城市监控系统数据库被发现没有密码保护

智能城市设计旨在让居民生活更轻松,但如果它的监控系统数据泄露?John Wethington 报告一个智能城市数据库没有密码保护可以直接通过浏览器访问。

来源:solidot.org

详情: http://t.cn/EoLAb4Q

(信息来源于网络,安华金和搜集整理)