比如,git已经commit了两个文件的修改,该commit包含两个文件的修改: A和B。
修改了好几次,最终决定不适用了A, 我们只保留B文件的修改,请问怎么操作?
https://www.cnblogs.com/Sir-Lin/p/7307865.html
# 1
git reset HEAD^ --soft
# 2
git reset HEAD A
# 3
git commit
唯一不好的一点就是,git这时候会产生一个新的commit id,如果我们使用gerrit系统的话,可以 提前把之前的 CHange-id抄过来,这样就可以接着使用原先的gerrit提交了。
说实话,目前这种我没有尝试过。
# 1
git rm --cached A
# 2
git commit --amend
systemd已经是大部分发行版的主流了,我们今天的这个问题是,解读其中的一个关键字眼。
systemd的unit是一个sections, 这篇文章 介绍的非常详细。
就拿rc.local的实例来讲:
[Unit]
Description=/etc/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.local
After=network.target
其中我们常见的还有 wants
字段,这个字段是一个弱强制性,也就是,当你的条件不满足时,不会影响到这个systemd的work。
但是还有一个requires
的字段就没有这么友善了,需要强制满足。
network.target has very little meaning during start-up. It only indicates that the network management stack is up after it has been reached. Whether any network interfaces are already configured when it is reached is undefined. Its primary purpose is for ordering things properly at shutdown: since the shutdown ordering of units in systemd is the reverse of the startup ordering, any unit that is order After=network.target can be sure that it is stopped before the network is shut down if the system is powered off. This allows services to cleanly terminate connections before going down, instead of abruptly losing connectivity for ongoing connections, leaving them in an undefined state. Note that network.target is a passive unit: you cannot start it directly and it is not pulled in by any services that want to make use of the network. Instead, it is pulled in by the network management service itself. Services using the network should hence simply place an After=network.target dependency in their unit files, and avoid any Wants=network.target or even Requires=network.target.
[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no
Type=
Configures the process start-up type for this service unit. One of simple, exec, forking, oneshot, dbus, notify or idle:
ExecStart=
Commands with their arguments that are executed when this service is started. The value is split into zero or more command lines according to the rules described below (see section “Command Lines” below).
总结一下就是: After
仅仅检查unit是否满足,但是并不会激活该units;Requires
是同时激活该service与需要的service,如果Requires
的service失败了
那么该service也不会启动。
摘抄如下:
One of the major difference is,
After only checks if the unit is activated already, and does not explicitly activate the specified units. The units listed in Requires are activated together with the unit. If any of the required units fail to start, the unit is not activated. Consider I have a unit file test-app.service,
[Unit]
Description=test app
After=network-online.target
Here is what will happen when this statement is executed,
After checks if network-online.target. if network-online.target not started, it will wait. test-app starts only after network-online.target is active If I had Requires instead,
[Unit]
Description=test app
Requires=network-online.target
Here is what will happen when this statement is executed,
network-online.target and test-app are activated together if network-online.target fails to start test-app will not be activated.
Refer to https://makefiletutorial.com/
# Thanks to Job Vranish (https://spin.atomicobject.com/2016/08/26/makefile-c-projects/)
TARGET_EXEC := EswinE2r
BUILD_DIR := ./build
SRC_DIRS := ./src
INC_DIRS := ./include
CC := ../../../../../tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc
CXX := ../../../../../tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
AR := ../../../../../tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ar
STRIP := ../../../../../tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-strip
# Find all the C and C++ files we want to compile
SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c)
# String substitution for every C/C++ file.
# As an example, hello.cpp turns into ./build/hello.cpp.o
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
# String substitution (suffix version without %).
# As an example, ./build/hello.cpp.o turns into ./build/hello.cpp.d
DEPS := $(OBJS:.o=.d)
# Every folder in ./src will need to be passed to GCC so that it can find header files
INC_DIRS := $(shell find $(INC_DIRS) -type d)
# Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
# The -MMD and -MP flags together generate Makefiles for us!
# These files will have .d instead of .o as the output.
CPPFLAGS := $(INC_FLAGS) -MMD -MP
# The final build step.
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
$(CC) $(OBJS) -o $@ $(LDFLAGS)
# Build step for C source
$(BUILD_DIR)/%.c.o: %.c
mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INC_FLAGS) -c $< -o $@
# Build step for C++ source
#$(BUILD_DIR)/%.cpp.o: %.cpp
# mkdir -p $(dir $@)
# $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
.PHONY: clean
clean:
rm -r $(BUILD_DIR)
# Include the .d makefiles. The - at the front suppresses the errors of missing
# Makefiles. Initially, all the .d files will be missing, and we don't want those
# errors to show up.
-include $(DEPS)
还有一种模板,但是我不太清楚里面的用法,先看下代码:
#include ../../common.mk
EXECUTABLE = test
OBJ_BASE_DIR := objs
HOST_ARCH := $(shell uname -m)
TARGET_ARCH := $(HOST_ARCH)
OBJDIR := $(OBJ_BASE_DIR)/$(TARGET_ARCH)/release
SOURCEDIR := src
SRCS := $(wildcard $(SOURCEDIR)/*.c)
OBJS := $(patsubst $(SOURCEDIR)/%c, $(OBJDIR)/%o, $(SRCS))
INCPATH := -Iinclude
ifeq ($(HOST_ARCH), x86_64)
ifeq ($(ARCH), )
else ifneq ($(findstring $(ARCH), aarch64 arm64),)
TARGET_ARCH := aarch64
CROSS_CC := 1
CC := ../../../tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc
CXX := ../../../tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
AR := ../../../tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ar
STRIP := ../../../tools/gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-strip
else ifneq ($(ARCH), $(HOST_ARCH))
$(error $(ARCH) is not supported on $(HOST_ARCH) )
endif
else
ifeq ($(ARCH), )
else ifneq ($(ARCH), $(HOST_ARCH))
ifneq ($(ARCH)_$(HOST_ARCH), arm64_aarch64)
$(error $(ARCH) is not supported on $(HOST_ARCH) )
endif
endif
endif
.PHONY : all dir
all: dir $(EXECUTABLE)
dir:
@mkdir -p $(OBJDIR)
$(EXECUTABLE): $(OBJS)
$(CC) $^ -o $@
@echo ++++++ $(EXECUTABLE) is generated successfully!!! ++++++
$(OBJS): $(OBJDIR)/%.o: $(SOURCEDIR)/%.c
$(CC) $(CFLAGS) -o $@ -c $< $(INCPATH)
$(OBJDIR)/%.d : %.c
@set -e; rm -rf $@; mkdir -p $(OBJDIR); \
$(CC) -MM $(CFLAGS) $(INCPATH) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\$(OBJDIR)\/\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
-include $(OBJS:.o=.d)
.PHONY : clean
clean:
$(RM) $(OBJ_BASE_DIR)
$(RM) $(EXECUTABLE)
其中,我不太明白的是 $(OBJDIR)/%.d: %.c
这句话是什么意思。还有一点是,我们的连接的有文件 -Iinclude
或者
-Llibxx
,这个连接标志一般是放在定义的位置,我们不在规则里去显性的使用这个标志,,,一般情况下。
CC := gcc
RM := rm -rf
OBJDIR := objs
CFLAGS := -Wall
EDKLIB := xxsdk
TARGET_ARCH := $(shell uname -m)
EXECUTABLE = rtmp_push
SRCS := rtmp_push.c
OBJS := $(patsubst %c, $(OBJDIR)/%o, $(SRCS))
INCPATH := -I/usr/include/eswin
LIBPATH := /usr/lib/eswin/${TARGET_ARCH}
LIB := -L$(LIBPATH) -Wl,-rpath=$(LIBPATH) -l$(EDKLIB)
.PHONY : all dir
all: dir $(EXECUTABLE)
dir:
@mkdir -p $(OBJDIR)
$(EXECUTABLE): $(OBJS)
$(CC) $^ -o $@ $(LIB)
@echo ++++++ $(EXECUTABLE) is generated successfully!!! ++++++
$(OBJS): $(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $< $(INCPATH)
.PHONY : clean
clean:
$(RM) $(OBJDIR)
$(RM) $(EXECUTABLE)
先看代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#define EXIT_ERR(m) \
do\
{\
perror(m);\
exit(EXIT_FAILURE);\
}\
while (0)
static int fd;
void recovery_signal_handle(int signum)
{
unsigned int val = 0;
int status;
read(fd, &val, 1);
if (val == 0){
sleep(7);
if (val == 0) {
printf("I'm pretty sure that recovery button is pushed down, go and boot from B slot!!!\n");
//status = system("nvbootctrl -t bootloader set-active-boot-slot 1");
//printf("nvbootctrl -t bootloader set-active-boot-slot 1\n");
status = system("nvbootctrl -t rootfs set-active-boot-slot 1");
printf("nvbootctrl -t rootfs set-active-boot-slot 1\n");
if (status == -1) {
EXIT_ERR("system nvbootctrl error");
}else {
printf("Now this station is going to reboot...\n");
sleep(1);
status = system("reboot");
if (status == -1) {
EXIT_ERR("system reboot error");
}
}
}
}
}
int main(int argc, char **argv)
{
int Oflags;
//SIGIO, driver sends this signal to note that Interrupt is coming.
signal(SIGIO, recovery_signal_handle);
fd = open("/dev/recovery", O_RDWR);
if (fd < 0)
printf("can't open!\n");
//set the process ID that will receive SIGIO signal for events on the fd.
fcntl(fd, F_SETOWN, getpid());
//get the file status flags
Oflags = fcntl(fd, F_GETFL);
//set the file status flags to Oflags | FASYNC.
//You could find "#define FASYNC O_ASYNC" in fcntl.h of glibc.
//O_ASYNC means generating a signal when input or output becomes possible on this fd.
fcntl(fd, F_SETFL, Oflags | FASYNC);
while (1){
sleep(1000);
}
return 0;
}
然后看一下内核源代码是怎么写的:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h> // Required for the GPIO functions
#include <linux/interrupt.h> // Required for the IRQ code
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
//#include <linux/device.h>
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");
static int major;
static struct class *vimer_recovery_class;
static struct device *vimer_recovery_class_dev;
static unsigned int recovery_button = 393; //GPIO01--421,GPIO11--422,GPIO13--393
static unsigned int irq_number;
static struct fasync_struct *recovery_async;
static irq_handler_t vimer_recovery_irq_handler( unsigned int irq, void *dev_id, struct pt_regs *regs )
{
printk(KERN_INFO "RECOVERY_TEST:: interrupt received! (recovery button state is %d)\n", gpio_get_value(recovery_button));
//deliver a signal to interested processes(userspace) when the interrput comes.
if (recovery_async) {
kill_fasync(&recovery_async, SIGIO, POLL_IN);
}
return (irq_handler_t) IRQ_HANDLED;
}
static int vimer_recovery_fasync(int fd, struct file *filp, int on)
{
printk("driver: vimer_recovery_fasync\n");
//add files to or remove files from the lists of interested processes when the FASYNC flag changes for an open file.
return fasync_helper(fd, filp, on, &recovery_async);
}
static int vimer_recovery_open(struct inode *inode, struct file *filp)
{
int result = 0;
printk(KERN_INFO "RECOVERY_TEST:: Initializing the RECOVERY_TEST LKM\n");
gpio_request(recovery_button, "sysfs");
gpio_direction_input(recovery_button);
gpio_set_debounce(recovery_button, 200);
gpio_export(recovery_button, false);
printk(KERN_INFO "RECOVERY_TEST:: the current state of recovery button is: %d\n", gpio_get_value(recovery_button));
irq_number = gpio_to_irq(recovery_button);
printk(KERN_INFO "RECOVERY_TEST:: the recovery button is mapped to IRQ: %d\n", irq_number);
result = request_irq(irq_number,
(irq_handler_t) vimer_recovery_irq_handler,
IRQF_TRIGGER_FALLING,
"vimer_recovery_handler",
NULL);
if( result < 0 )
{
printk(KERN_INFO "RECOVERY_TEST:: request_irq returns ERROR: %d, please kindly check\n", result);
}
return result;
}
static ssize_t vimer_recovery_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
unsigned int val;
int ret;
val = gpio_get_value(recovery_button);
ret = copy_to_user(buf, &val, 1);
return 1;
}
static int vimer_recovery_close(struct inode *inode, struct file *filp)
{
printk(KERN_INFO "RECOVERY_TEST:: the current state of recovery button is: %d\n", gpio_get_value(recovery_button));
free_irq(irq_number, NULL);
gpio_unexport(recovery_button);
gpio_free(recovery_button);
vimer_recovery_fasync(-1, filp, 0);
printk(KERN_INFO "RECOVERY_TEST:: close from the LKM!\n");
return 0;
}
static struct file_operations vimer_recovery_fops =
{
.owner = THIS_MODULE,
.open = vimer_recovery_open,
.read = vimer_recovery_read,
.release = vimer_recovery_close,
.fasync = vimer_recovery_fasync,
};
int vimer_recovery_init(void)
{
major = register_chrdev(0,"vimer_recovery", &esw_recovery_fops);
vimer_recovery_class = class_create(THIS_MODULE, "esw_recovery");
vimer_recovery_class_dev = device_create(esw_recovery_class, NULL, MKDEV(major, 0), NULL, "recovery"); /* /dev/recovery */
return 0;
}
void vimer_recovery_exit( void )
{
unregister_chrdev(major, "vimer_recovery");
device_unregister(vimer_recovery_class_dev);
class_destroy(vimer_recovery_class);
}
module_init(vimer_recovery_init);
module_exit(vimer_recovery_exit);
近日,有一点需求是关于 先文本化shell脚本,然后在脚本中调用相关的语句把 这些命令写入另一个可执行的shell脚本中,以下是具体的两种方式。
我个人是比较喜欢这种方式的:
cat >${PACKAGE_DIR}/DEBIAN/control<<EOF
Source: eswin ms bsp
Section: unknown
Priority: optional
Maintainer: Eswin
Build-Depends: debhelper (>= 10)
Standards-VERSION: 4.1.2
Homepage: http://eswin.com/
Package: eswin-ms-bsp-replace-logo
Pre-Depends: dpkg (>= 1.16.1)
Depends: locales (>= 2.3.6)
VERSION: ${VERSION}
Architecture: ${ARCH}
Description: ESWIN® BSP replace logo
EOF
这样,${PACKAGE_DIR}/DEBIAN/control 这个文本连创建都不用了,直接可以使用。
POSTINST_CONT="#!/bin/bash\n
#1. copy login logo\n
cp $INSTALL_DIR_1/$LOGIN_LOGO /usr/share/backgrounds/\n
sed "s/NVIDIA_Login_Logo.png/${LOGIN_LOGO}/g" /etc/skel/.xsessionrc
\n
#2. Copy wallpaper logo\n
cp ${INSTALL_DIR_1}/${WALLPAPER_LOGO} /usr/share/backgrounds\n
sed "s/NVIDIA_Wallpaper.jpg/${WALLPAPER_LOGO}/g" /etc/xdg/autostart/nvbackground.sh\n
"
把这个内容输出到文本中:
$(echo -e ${POSTINST_CONT} > ${PACKAGE_DIR}/DEBIAN/postinst)
注意,这里的shell文本必须使用双引号,单引号是不行的。
pcmanFM:文件管理器
lxpanel:桌面面板
lxsession:会话管理工具
lxappearance:gtk+主题更换工具
openbox:轻量窗口管理器
leafpad:轻量级编辑器,类似于记事本
xarchiver:超级轻量的解压(压缩)软件
lxnm:轻量级网络管理器
LXTerminal:模拟终端程序
ubuntu18.04.5 LTS 默认使用的gnome 3.28.5
文件管理 Nautilus
桌面面板 gnome-panel
会话管理工具 gnome-session
窗口管理器 mutter
看图工具 shotwell
编辑器 gedit
网络管理器 network-manager
终端 gnome-termina
文件管理 Nautilus
窗口管理器 mutter
编辑器 gedit+leafpad
网络管理器 NetworkManager
终端 gnome-terminal
关于桌面系统,Linux下有两个概念
Display Manager:显示管理系统。 Desktop Environment: 桌面环境。 顾名思义,DM负责显示,DE负责创建用户操作的界面。两者都有不同的选项,并且没有强绑定或强依赖的关系,不同的DM可以支持不同的DE。
从用户角度来看,DM提供登录界面,DE提供登录后的桌面。
在Ubuntu18.04上,默认选择的DM是GDM3,DE是Unity,这两者都是相对重量级的系统,资源占用多,加载时间长,当然也带来相对好的视觉效果。