分类 Linux 下的文章

如何修复linux系统中的grub?

Environment

  • ubuntu
  • grub

Intro

The rescue mode is a major GRUB 2 enhancement. If GRUB 2 fails to find a useable grub.cfg and is unable to transfer control to a kernel it will drop to a grub-rescue> prompt. From this prompt the user can investigate problems, make changes, and retry the boot.

Steps

ls

This will display the known devices and partitions. From this information, the user must determine the device and partition on which the system is installed.

set prefix=(hdX,Y)/boot/grub

If incorrect, "no such disk" or "not found" errors will occur later.

set root=(hdX,Y)********

In this command, X is the device/drive, starting with 0. Y is the partition, starting with 1. Example: (hd0,1) is sda1. (hd2,5) is sdc5.

set

Inspect the "prefix=" listing. It should match the root designation in Step 3, in the following format: prefix=(hdX,Y)/boot/grub.

ls /boot

Inspect the contents. The user should see varioius kernels, initrd images and the grub folder. If not, use the ls command to inspect the device and attempt to find these files and folders. If necessary, set another device as root.

insmod /boot/grub/linux.mod

Load (insert module) the linux module. Without this module loaded, the user will receive an "Unknown command linux" message when trying to load the kernel.

linux /vmlinuz root=/dev/sdXY ro

Load the linux kernel, substituting the correct designations for "X" and "Y" (example: sda1). The user will see a message showing the kernel has been loaded.

initrd /initrd.img

Load the initrd image. When pressing ENTER the user may or may not see a message in the terminal.

boot

Attempt to boot using the information entered.

These changes are not permanent. After successfully booting into the system the user should run sudo update-grub and inspect the GRUB 2 configuration file (/boot/grub/grub.cfg).The user may need to reinstall GRUB 2 using sudo grub-install /dev/sdX.

ubuntu下lvm扩容

软硬件环境

  • ubuntu 16.04 64bit

前言

机器用久了,慢慢地,硬盘空间就不够用了,然后就去买了新硬盘,如何在不动现有系统的情况下无缝的安装新硬盘,达到快速扩容的目的,本文就来解决这个问题。这里有个前提,就是ubuntu系统安装时需要创建LVM。

LVM是什么

LVM,即Logical Volume Manager,逻辑卷管理。LVM可以方便地将一个或多个硬盘在逻辑上集合起来,相当于一个大硬盘。

LVM实战

电脑中原来有一块硬盘,2.7TB,手头上还有另外3块新的SATA硬盘,现在需要将这余下的3块新硬盘添加到电脑中,达到扩容的目的。

lvm_01

把3块新硬盘接到电脑上,查看磁盘情况

lvm_02

处理第一块硬盘/dev/sdb,进入到fdisk命令后,n为创建新分区,回车选择默认值,t为选择类型,一定要选8e,意即LVM

lvm_03

lvm_04

最后执行w命令进行保存

lvm_05

接下来创建PV,Physical Volume,物理卷是指硬盘分区或从逻辑上与磁盘分区具有同样功能的设备(如RAID),是LVM的基本存储逻辑块,但和基本的物理存储介质(如分区、磁盘等)比较,多了一些与LVM相关的管理参数

lvm_06

查看VG,Volume Group:LVM卷组类似于非LVM系统中的物理硬盘,其由物理卷组成。可以在卷组上创建一个或多个“LVM分区”(逻辑卷),LVM卷组由一个或多个物理卷组成

lvm_07

这里的longjingdata-vg就是vgdisplay输出的VG Name

lvm_08

lvextend -L +2T /dev/longjingdata-vg/root
resize2fs /dev/longjingdata-vg/root

这样一块新硬盘就添加成功了,其余的2块,依照上面的操作依样画葫芦就行了,这里不再赘述。

最后查看下结果,满足预期。

lvm_09

进程间通信之消息队列

软硬件环境

  • ubuntu 16.04 64bit

简介

消息队列是系统内核提供的一个用来保存消息的队列,是进程间通信的一种常用方法

相关数据结构

1、msgbuf

struct msgbuf
{
    long mtype;    /消息类型/
    char mtext[1]; /消息内容/
}

mtext不受其描述的限制,实际上mtext不仅可以保存字符,而且能保存任何形式的数据。因此程序员可以重新定义结构

struct mymsgbuf{
    long mtype;         /* 消息类型 */
    long request_id;    /* 请求标识符 */
    struct client info; /* 客户消息结构 */
}; 

需要注意的一点是,linux系统对消息类型的最大升序有所限制,在/usr/include/linux/msg.h中。

define MSGMAX 8192

2、msqid_ds

struct msqid_ds 
{
    struct ipc_perm msg_perm;     /消息队列的存取权限及其它一些信息,参见ipc_perm/
    struct msg msg_first;        / first message on queue,unused */
    struct msg msg_last;         / last message in queue,unused */
    __kernel_time_t msg_stime;    /* last msgsnd time */
    __kernel_time_t msg_rtime;    /* last msgrcv time */
    __kernel_time_t msg_ctime;    /* last change time */
    unsigned long msg_lcbytes;    /* Reuse junk fields for 32 bit */
    unsigned long msg_lqbytes;    /* ditto */
    unsigned short msg_cbytes;    /* current number of bytes on queue */
    unsigned short msg_qnum;      /* number of messages in queue */
    unsigned short msg_qbytes;    /* max number of bytes on queue */
    __kernel_ipc_pid_t msg_lspid; /* 最近一次向队列发送消息的进程的pid */
    __kernel_ipc_pid_t msg_lrpid; /* 最近一次从队列中取出的消息的进程的pid */
};

3、msg

struct msg
{
    struct msg msg_next;  /消息链表中的再一节点指针*/
    long msg_type;         /和结构msgbuf中的mtype一样/
    char msg_spot;        /消息内容,和msgbuf中的mtext一样*/
    time_t msg_stime;      /msgsnd time/
    short msg_ts;          /消息长度/
}; 

4、ipc_perm

struct ipc_perm
{
    __kernel_key_t    key;
    __kernel_uid_t    uid;
    __kernel_gid_t    gid;
    __kernel_uid_t    cuid;
    __kernel_gid_t    cgid;
    __kernel_mode_t    mode; 
    unsigned short    seq;
};    

这个结构用来保存每个IPC对象的权限信息

相关函数

1、ftok()

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id); 

ftok()通过混合pathname所指文件的inode和minor device的值以及proj_id的值来产生关键字,示例

key_t key;
key = ftok(".","a"); //程序在同一目录下运行

2、msgget()

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);

msgget()用来创建新的消息队列或者获取已有的消息队列。其中key是消息队列的关键字,用它来和已有的消息队列对象的关键字进行比较来判断消息队列是否已经创建,msgflg可取如下值

  • IPC_CREAT: 如果消息队列不存在,则创建,否则打开

  • IPC_EXCL  : 与IPC_CREAT一起使用,IPC_CREAT | IPC_EXCL,如果消息队列不存在,则创建,否则返回错误

    除此以外,在msgflg中还可以和存取权限结合使用

    msgget()返回新建的消息队列对象的标识符,如果队列已经存在,返回-1

3、msgsnd()

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 

msgsnd()用来向消息队列发送消息。msgid是消息队列对象的标识符(由msgget()得到),msgp指向消息所在的内存,msgsz是消息长度,msgsz = sizeof(struct mymsgbuf) - sizeof(long);
msgflg可取如下值

  • IPC_NOWAIT: 如果队列已满,消息不再写入队列,控制权返回调用函数的进程。如果不指定,进程将被阻塞直到消息可以被写入
  • 0    : 忽略标志位

4、msgrcv()

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

msgrcv()用来从消息队列中取出消息。msgtype指定从消息队列中所取的消息的类型,如果msgtype为0,则不做类型检查直接返回队列中最旧的消息。
    msgflg可以取如下值

  • IPC_NOWAIT:  如果消息队列为空,返回ENOMSG,控制权交给调用函数的进程,如果不指定这个参数,进程将被阻塞直到可以从队列中取出符合条件的消息为止。如果一个client正在等待的队列被删除,返回EIDRM。如果进程在阻塞等待过程中收到系统的中断信号,则返回EINTR
  • MSG_NOERROR:  如果函数取得的消息长度大于msgsz,将只返回msgsz长度的信息,剩余部分被丢弃。如果不指定这个参数,返回E2BIG,消息不被取出
  • 0          : 忽略标志位

5、msgctl()

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

msgctl()用来控制消息队列的行为。参数cmd是可对消息队列进行的操作

  • IPC_STAT: 取出消息队列的msqid_ds数据,并存入buf中
  • IPC_SET : 设置消息队列的msqid_ds结构中的msg_perm成员,设定的值由buf指向的msqid_ds结构给出
  • IPC_EMID: 将队列从内核中删除

如何将TS流中的mjdutc时间转换成标准utc时间

软硬件环境

  • ubuntu 16.04 64bit

前言

在EIT表中,有一个字段start_time来描述节目开始的时间,它是一个总共40bit的数值,包含以MJD和UTC表示的时间及日期。其中前16bit表示MJD日期,其余24bit按4bit BCD编码,表示6个数字。如下图所示

本文就来将它转换成标准UTC时间。

什么是MJD

百度百科的解释

儒略日(Julian day,JD)是指由公元前4713年1月1日,协调世界时中午12时开始所经过的天数,多为天文学家采用,用以作为天文学的单一历法,把不同历法的年表统一起来。如果计算相隔若干年的两个日期之间间隔的天数,利用儒略日就比较方便。

什么是UTC

协调世界时(英:Coordinated Universal Time ,法:Temps Universel Coordonné),又称世界统一时间,世界标准时间,国际协调时间。英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。

转换成UTC

以下是C语言的转换实现代码

//这里的p_byte就是start_time时间
struct tm tm;
double mjd;
int k = 0;

memset(&tm, 0, sizeof(tm));
mjd = (p_byte[0] << 8) | p_byte[1];

tm.tm_year = (int) ((mjd - 15078.2) / 365.25);
tm.tm_mon = (int) (((mjd - 14956.1) - (int) (tm.tm_year * 365.25)) / 30.6001);
tm.tm_mday = (int) mjd - 14956 - (int) (tm.tm_year * 365.25) - (int) (tm.tm_mon * 30.6001);

if ((tm.tm_mon == 14) || (tm.tm_mon == 15))
    k = 1;

tm.tm_year += k;
tm.tm_mon = tm.tm_mon - 2 - k * 12;

/*
 * bcd码转化成int
 * */
tm.tm_sec = p_byte[4]-(p_byte[4] >> 4)*6;
tm.tm_min = p_byte[3]-(p_byte[3] >> 4)*6;
tm.tm_hour = (p_byte[2]-(p_byte[2] >> 4)*6) + 8;

p_tot->i_utc_time = mktime(&tm);

备注

如果是要计算北京时间,则需要在上述转换之后的基础上再加上8个小时,因为北京是处于东八区。

Ubuntu桌面通知

软硬件环境

  • ubuntu
  • notify-osd
  • libnotify-bin

概述

D-Bus是一种消息总线系统,它为应用程序之间互相调用提供了更为简单的方法。本文中实现的桌面通知就是基于D-Bus机制。桌面通知在ubuntu系统的早期版本中就有应用,如常见的音量调节、thunderbird的来信通知、QQ消息通知等都是如此。

先给一张系统架构图,方便理解。

notify_01

为简单起见,在这里称请求方为Client,响应请求的为Server。

Server

sudo apt-get source notify-osd    
cd notify-osd-0.9.24    
vi notify-osd/src/default.c

#define DEFAULT_DESKTOP_BOTTOM_GAP 6.0f
#define DEFAULT_BUBBLE_WIDTH 24.0f
#define DEFAULT_BUBBLE_MIN_HEIGHT 5.0f
#define DEFAULT_BUBBLE_MAX_HEIGHT 12.2f
#define DEFAULT_BUBBLE_VERT_GAP 0.5f
#define DEFAULT_BUBBLE_HORZ_GAP 0.5f
#define DEFAULT_BUBBLE_SHADOW_SIZE 0.7f
#define DEFAULT_BUBBLE_SHADOW_COLOR "#000000"
#define DEFAULT_BUBBLE_BG_COLOR "#131313"
#define DEFAULT_BUBBLE_BG_OPACITY "#cc"
#define DEFAULT_BUBBLE_HOVER_OPACITY "#66"
#define DEFAULT_BUBBLE_CORNER_RADIUS 0.375f
#define DEFAULT_CONTENT_SHADOW_SIZE 0.125f
#define DEFAULT_CONTENT_SHADOW_COLOR "#000000"
#define DEFAULT_MARGIN_SIZE 1.0f
#define DEFAULT_ICON_SIZE 3.0f
#define DEFAULT_GAUGE_SIZE 0.625f
#define DEFAULT_GAUGE_OUTLINE_WIDTH 0.125f
#define DEFAULT_TEXT_FONT_FACE "Sans"
#define DEFAULT_TEXT_TITLE_COLOR "#ffffff"
#define DEFAULT_TEXT_TITLE_WEIGHT TEXT_WEIGHT_BOLD
#define DEFAULT_TEXT_TITLE_SIZE 1.0f
#define DEFAULT_TEXT_BODY_COLOR "#eaeaea"
#define DEFAULT_TEXT_BODY_WEIGHT TEXT_WEIGHT_NORMAL
#define DEFAULT_TEXT_BODY_SIZE 0.9f
#define DEFAULT_PIXELS_PER_EM 10.0f
#define DEFAULT_SYSTEM_FONT_SIZE 10.0f
#define DEFAULT_SCREEN_DPI 96.0f
#define DEFAULT_GRAVITY GRAVITY_NORTH_EAST

Note

DEFAULT_GRAVITY可以取如下3个值
* GRAVITY_NONE: the behaviour in Jaunty. A notification will always go into the top right corner.    

* GRAVITY_EAST: the behaviour NotifyOsd has been having for about a week in Karmic's development cycle, with the notifications centered vertically on the screen.    

* GRAVITY_NORTH_EAST: the Karmic behaviour. Works like GRAVITY_NONE but does not put asynchronous notifications on top of the screen, even if there is no synchronous notification being displayed.

./configure    
make    
make install(if you need)    

Client

sudo apt-get install libnotify-bin

Have a test

  1. 启动server

    notify-osd/src/notify-osd

  2. 修改文字显示大小
    将 DEFAULT_TEXT_TITLE_SIZE 改为4.0f

  3. Client发送请求

    notify-send "djstava" "I Love It"

notify_02

桌面通知的python实现

  1. 安装pynotify模块
    http://www.galago-project.org/downloads.php下载notify-python-0.1.1.tar.gz,解压然后进行安装三部曲./configure、make、sudo make install

  2. 模块的使用

    try:
    import pynotify
    if pynotify.init('Fist Test'):

         n = pynotify.Notification('Title','message')
         n.show()
    
     else:
    
         print 'Pynotify module not initialized'
    except:
    
     print 'Pynotify module not installed'
    


    可以像下面一样来设置消息的紧急级别

    n.set_urgency(pynotify.URGENCY_LOW)
    n.set_urgency(pynotify.URGENCY_NORMAL)
    n.set_urgency(pynotify.URGENCY_CRITICAL)

关闭消息通知操作
    n.close()

参考资料

1、http://kobesearch.cpan.org/htdocs/Desktop-Notify/Desktop/Notify.pm.html
2、http://www.galago-project.org/specs/notification/0.9/index.html
3、https://wiki.ubuntu.com/NotifyOSD
4、http://doc.trolltech.com/4.2/intro-to-dbus.html
5、http://www.freedesktop.org/wiki/Software/dbus