张帅依的博客

积累点滴.

C语言学习

VA_ARGS

可变参数宏,如果可变参数被忽略或为空, ‘##’操作将使预处理器(preprocessor)去除掉它 前面的那个逗号

#define dePrintf(X,...) printf("[%s %s: %d]" X, __FILE__, __func__, __LINE__, ##__VA_ARGS__)

cpp引用c函数库

#ifdef __cplusplus
extern "C"{
#endif
/* c++引用C,将#include "x264.h"放到extern "C" 中 */
#include "x264.h"
#ifdef __cplusplus
}
#endif

Android Jni编写

java文件编写

package com.example.jni

public class Testjni {
    public native int jniRead(byte[] data, int len);
    public native int jniWrite(byte[] data, int len);
    static {
        System.loadLibrary("myJni");
    }
}

jni文件编写

jni文件的函数名要和java中的方法名对应起来,在jni中申请的空间要注意释放。

#include <jni.h>
#include <android/log.h>

#define LOG_TAG "myJni.c"
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA__ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA__ARGS__)

jint Java_com_example_jni_jniRead(JNIEnv *env, jobject thiz,
    jbyteArray receiveBuf, jint slen) {
    uint8_t p_recv_buf[256] = {0};
    int len = slen;
    len = read(fd, p_recv_buf, slen);
    LOGI("rea len:%d\n", len);
    (*env)->setByteArrayRegion(env, receiveBuf, 0, len,
        (const jbyte*)p_recv_buf);
    return len;
}

jint Java_com_example_jni_jniWrite(JNIEnv *env, jobject thiz,
    jbyteArray sendBuf, jint len) {
    //申请空间
    jbyte *sendelems = (*env)->GetByteArrayElements(env, sendBuf, NULL);
    ...//处理函数
    //释放
    (*env)->ReleaseByteArrayElements(env, sendBuf, sendelems, 0);
    return 0;
}

Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES:= \
    myJni.c
LOCAL_LDLIBS := -llog

LOCAL_SHARED_LIBRARIES += libam_adp liblog libcutils
LOCAL_C_INCLUDES += ../inc
#编译生成libmyJni.so
LOCAL_MODULE := libmyJni
#编译动态库
include $(BUILD_SHARED_LIBRARY)

执行mm编译。(菜鸟级别解释::=是赋值的意思,+=是追加的意思,$是引用某变量的值)补充说明:BUILD_EXECUTABLE表示以一个可执行程序的方式进行编译,include $(BUILD_PACKAGE)则是编译出一个apk,include $(BUILD_STATIC_JAVA_LIBRARY)则是编译出jar包。

LOCAL_MODULE_TAGS说明

LOCAL_MODULE_TAGS :=user eng tests optional
user: 指该模块只在user版本下才编译
eng: 指该模块只在eng版本下才编译
tests: 指该模块只在tests版本下才编译
optional:指该模块在所有版本下都编译
我一般都使用optional

我的例子

javah生成h文件

在src目录下执行javah -jni com.example.jni.Getso后生成com_example_jni_Getso.h

Linux驱动

交叉编译

编译ko文件

Makefile:
PWD=$(shell pwd)
KDIR=/xx/xx/linux-3.4

obj-m+=scr.o
scr-objs := file1.o file2.o test-scr.o

build:
    $(MAKE) -C $(KDIR) M=$(PWD)

clean:
    @rm -rf *.o *.ko *.cmd *.mod.c *.order *.symvers *.tmp_versions *~

执行编译:

make ARCH=arm CROSS_COMPILE=/xx/xx/arm-linux-gnueabi-

创建设备

class_create和device_create函数,在/dev下创建设备节点

int my_device_major = register_chrdev(0, "myDevice", &my_device_fops);
struct class* my_device_class = class_create(THIS_MODULE, "myDevice");
//在/sys/class下创建了myDevice目录
if (IS_ERR(my_device_class))
    return -1;
device_create(my_device_class, NULL, MKDEV(my_device_major, 0), NULL, "myDevice");
//在/dev下创建myDevice设备

自旋锁spinlock_t

spin_lock_irqsave会关闭中断

spinlock_t rx_slock;
spin_lock_init(&rx_slock);  //初始化
/* 使用 */
unsigned long flags;
spin_lock_irqsave(&rx_slock, flags);
...
//处理
...
spin_unlock_irqrestpre(&rx_slock, flags);

poll

驱动poll_wait

wait_queue_head_t rd_wq;
init_waitqueue_head(&rd_wq);

unsigned int test_poll(struct file *filp, struct poll_table_struct *wait){
    unsigned int ret = 0;
    poll_wait(filp, &rd_wq, wait);
    ...//处理
    if (hasData) ret |= POLLIN|POLLRDNORM;
    return ret;
}

当收到数后:wake_up_interruptible(&rd_wq);

应用poll

int fd = open("/dev/xxx", O_RDWR);
uint32_t timeout = xxxxx;
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, timeout);
if (ret!=1)
    return -1;
ret = read(fd, (void*)data, *size);

workqueue工作队列在中断中使用

使用:在有大量的中断处理中,需要紧急处理的中断直接在中断处理函数中进行,可以延迟处理的中断放到了workqueue中做,(不知这样对不对,我看网上还有一种tasklet)。workqueue的使用:

struct work_struct device_work;
struct workqueue_struct *device_wq;

void device_work_func(struct work_struct *work) {
    ...//处理中断的函数
}
//中断回调函数
irqreturn_t device_irq_service(int irqno, void *dev_id) {
    unsigned int temp;
    unsinged long flags;
    //加锁
    spin_lock_irqsave(&rx_slock, flags);
    temp = my_get_device_interrupt_status();//一般都可以从寄存器中读到中断状态
    if (temp&MY_DEVICE_IMMEDIATE) { //需要立即处理的紧急中断
        ...//中断处理
    } else {
        queue_work(device_wq, &device_work);
    }
    spin_unlock_irqrestpre(&rx_slock, flags);
}

//初始化
device_wq = create_singlethread_workqueue("device_wq");//只创建一个内核线程
INIT_WORK(&device_work, device_work_func);
request_irq(my_irq_no, device_irq_service, 0, "my_device", NULL);//注册中断服务

补充: 1. 中断处理中尽量不要加打印; 2. 在硬中断处理函数device_irq_service中不能使用mutex_lock,如果必须加锁可使用自旋锁spinlock_t; 在软中断 函数device_work_func中可以加mutex_lock

智能卡

智能卡ATR

一般来说只要VCC上电CLK有时钟(电压要对应,data保持上拉),这时只用给RST持续一段时间的低电平,智能卡就会主动回复ATR。智能卡可以直接使用5V供电,目前还没遇到过只工作在3V的卡,一般工作电压在2.7-5.5V,但遇到过工作电压是4.75-5.25V的卡。
ATR最长33字节,ATR的各数据位之间可能也有一段的时间间隔,这些在7816协议中都有规定。读ATR可以采用两种方式:按照协议边分析边读,这样按照协议读数结束就可以return了;也可以不管协议直接读,ATR中两个字节之间的间隔最长可以是9600etu,超时就认为ATR结束了。

反向

像NDS的卡数据是反向,可通过ATR第一个字节看出,一般判断0x03或0x3f为反向卡。反向指高低位倒过来,再取反(软件取反的话,可以通过查表的方式)

0x03
0 0 0 0 0 0 1 1 先高低倒过来
1 1 0 0 0 0 0 0 再取反
0 0 1 1 1 1 1 1 0x3f

数据传输

一般来说传输一个字符要12个etu=1 START + 8 DATA + 1 PARITY + 2 GUARD

Linux 学习

vim

:vsplit 将窗口分成两个,ctrl+w切换
:edit 打开文件
:%!xxd -g 1 :切换成十六进制的一个字节的模式
u 撤销上一步的操作
ctrl+r 恢复上一步被撤销的操作
shift+8 查找当前单词
ggVG 全选
q: 进入命令历史编辑
vim xxx +N 打开文件并跳到第N行
vim -d xx xxx 等同于 vimdiff xx xxx
:set noro 取消只读,在git difftool时很有用
dp将当前光标内容复制到另一窗口,do将另一窗口内容复制过来

tar

查看内容不解压:tar tvf xxx.tar.gz
解压:tar -xzvf xxx.tar.gz
解压到指定目录:tar -xzvf xxx.tar.gz -C /XX/XXX
压缩:tar -czvf xxx.tar.gz xxx/
解压:tar -xjvf xxx.tar.bz2
解压:tar xvJf xxx.tar.xz

mount

mount后让普通用户有读写权限,加参数-o umask=000

sudo mount /dev/sdb1 /mnt/ -o umask=000

挂载linux网络设备

mount -t nfs -o nolock 192.168.0.188:/share /mnt

pkg-config

查看头文件:pkg-config --cflags opencv
查找库文件:pkg-config --libs opencv
查看版本: pkg-config --modversion opencv

cp

连带目录一起复制: cp –parents -r xx/xx/xx/ xx/

sed

‘-i’使修改生效
a. 将old替换为new: sed ’s/old/new/g’ file -i
b. 删除第四行: sed ‘4 d’ file
c. 在第三行后添加一行: sed ‘3 a xxx’ file
d. 在第三行前添加一行: sed ‘3 i xxx’ file

find和grep

在.c文件中查找东西:find -name ‘*.c’ | xargs grep ‘xxx’

gcc编译时指定小端-EL

mips-linux-gnu-gcc -g -O2 -Wall -EL test.c

watch

检测一个命令的运行结果,默认2S间隔重复运行命令,用-n参数指定时间间隔: watch free

usermod

查看用户所属的组:groups user
添加用户到某个组:usermod -a -G groupA user

&&和||

command1 && command2 当command1执行成功才执行command2
command1 || command2 当command1执行不成功才执行command2

bg fg jobs和ctrl+z

  1. ctrl+z: 暂停进程,可使用jobs查看可看到状态为Stopped
  2. bg % [num]: 将job id为num的进程放到后台运行,job id通过jobs查看得到,此时查看状态为Running
  3. fg % [num]: 将job id为num的后台进程放到前台运行
  4. 命令后加& 是将命令放在后台执行

Android学习

包属性

sharedUserId

使用sharedUserId属性时取值需要包含点(dot),如android:sharedUserId=“test”安装时会提示:Failure [INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID]。使用android:sharedUserId=”zsy.test”就可以了。

Handler和HandlerThread

Handler会关联一个单独的线程和消息队列。Handler默认关联主线程,会在主线程执行,如果在这里面的操作会有阻塞,界面也会卡住。如果要在其他线程执行,可以使用HandlerThread

HandlerThread mHandlerThread = new HandlerThread("test");
mHandlerThread.start();
Handler mHandler = new Handler(mHandlerThread.getLooper()) {
    public void handlerMessage(Message msg) {
        XXX
    }
};

当要停止mHandlerThread时可执行:

mHandlerThread.quit();

Thread和Runnable

Java中Runnable和Thread的区别

在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限

在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:1.避免点继承的局限,一个类可以继承多个接口;2.适合于资源的共享

package org.demo.runnable;  
class MyThread implements Runnable{  
    private int ticket=10;  
    public void run(){  
        for(int i=0;i<20;i++){  
            if(this.ticket>0){  
                System.out.println("卖票:ticket"+this.ticket--);  
            }  
        }  
    }  
}  
package org.demo.runnable;  
public class RunnableTicket {  
    public static void main(String[] args) {  
        MyThread mt=new MyThread();  
        new Thread(mt).start();//同一个mt,但是在Thread中就不可以,如果用同一  
        new Thread(mt).start();//个实例化对象mt,就会出现异常  
        new Thread(mt).start();  
    }  
}; 

Button

使用Button的时候可以这么用:

public class MainActivity extends Activity implements View.OnClickListener {
    ...
    Button btn_ok = (Button) findViewById(R.id.btn_ok);
    btn_ok.setOnClickListener(this);
}

实现onClick(View v)方法,而且费时的按键响应操作使用Handler做

public void onClick(View v) {
    switch(v.getId()) {
    case R.id.btn_ok:
        Message m = new Message();
        m.what = XXXX;
        Bundle data = new Bundle();
        data.putString(XXX, XXXXX);
        m.setData(data);
        mHandler.sendMessage(m);
        break;
    }
}

mHandler的写法

private Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        switch(msg.what) {
        case XXX:
            String str = msg.getData().getString(XXX);
            break;
        }
    }
}

像素

px、dp和sp,这些单位有什么区别?
px指屏幕上物理像素点,不建议使用; 因为100px的图片在不同手机上显示的实际大小可能不同

You would use:    
    sp for font sizes
    dip for everything else.    
    dip==dp

adb及常用调试指令

开启adb功能:start adbd
查看设备:adb devices
多于一个设备时指定设备:adb -s 192.168.11.84:5555 shell
启动应用某界面:am start com.example.test/.MainActivity
命令行安装应用:pm install xxx.apk
命令行卸载应用:pm uninstall com.example.test
启动模拟器:./emulator -avd test -memory 512 -partition-size 256 启动名称为test的模拟器,rom大小256M

分析工具dumpsys

dumpsys用来给出android应用程序的信息:

dumpsys [Option]
        meminfo 内存信息
        cpuinfo cpu信息
        等很多选项
service list可以列出服务

mat使用

安装配置
How to enable Heap updates on my android client

签名文件

生成签名文件

keytool -genkey -alias sign.keystore -keyalg RSA -validity 20000 -keystore sign.keystore

签名

jarsigner -verbose -keystore sign.keystore -signedjar xxx_signed.apk xxx.apk sign.keystore

Android Usb Host

1. 检查系统是否开启了usb host功能

  确认/system/etc/permissions目录有android.hardware.usb.host.xml这个文件。

2. 查找设备

在AndroidManifest.xml中添加:
<intent-filter>
    <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />

res/xml/device_filter.xml的内容如下,注意为10进制数

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>

方法1

在<activity ...></activity>之间加intent-filter之间,这样当USB设备插入时会启动这个Activity,通过
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);获取设备

方法2

不用系统的广播的话,可以遍历设备列表,得到设备

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
    UsbDevice device = deviceIterator.next()
    //查找想要的设备
    if (device.getVenderId()==venderID && device.getProductId==productId)
        //your code
}

通过UsbManager的requestPermission方法申请usb权限 manager.requestPermission(device, null);会弹出选择框让用户选择是否允许应用访问usb设备。

3. 通信

官网例子

private Byte[] bytes
private static int TIMEOUT = 0;
private boolean forceClaim = true;
...
UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
UsbDeviceConnection connection = mUsbManager.openDevice(device); 
connection.claimInterface(intf, forceClaim);
connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread

获取usb设备端点

  UsbEndpoint ep = intf.getEndpoint(i);
  ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT;//中断
  ep.getDirection()==UsbConstants.USB_DIR_OUT;//相对主机来说

使用UsbRequest

发送

ByteBuffer mOutData = ByteBuffer.allocate(len);
UsbRequest mUsbRequest = new UsbRequest();
mUsbRequest.initialize(connection, mEndpointOut);
mUsbRequest.queue(mOutData, len);
if (connection.requestWait()==mUsbRequest)
    //成功

接收,不知道为什么在4.2上mInData要ByteBuffer.allocate(len*2)

//ByteBuffer mInData = ByteBuffer.allocate(len);//4.0
ByteBuffer mInData = ByteBuffer.allocate(len*2);
UsbRequest mUsbRequest = new UsbRequest();
mUsbRequest.initialize(connection, mEndpointIn);
mUsbRequest.queue(mInData, len);
if (connection.requestWait()==mUsbRequest)
    byte[] data = mInData.array();

测试文章

myself

archlinux安装

pacman

pacman -Sy abc                    和源同步后安装名为abc的包
pacman -S abc                     从本地数据库中得到abc的信息,下载安装abc包
pacman -Sf abc                    强制安装包abc
pacman -Ss abc                   搜索有关abc信息的包
pacman -Si abc                    从数据库中搜索包abc的信息
pacman -Syu                        同步源,并更新系统
pacman -Sy                          仅同步源
pacman -R abc                     删除abc包
pacman -Rc abc                   删除abc包和依赖abc的包
pacman -Rsn abc                 移除包所有不需要的依赖包并删除其配置文件
pacman -Sc                          清理/var/cache/pacman/pkg目录下的旧包
pacman -Scc                        清除所有下载的包和数据库
pacman -Sd abc                   忽略依赖性问题,安装包abc
pacman -Su --ignore foo       升级时不升级包foo
pacman -Sg abc                   查询abc这个包组包含的软件包
pacman -Q                           列出系统中所有的包
pacman -Q package             在本地包数据库搜索(查询)指定软件包
pacman -Qi package            在本地包数据库搜索(查询)指定软件包并列出相关信息
pacman -Q | wc -l                  统计当前系统中的包数量
pacman -Qdt                         找出孤立包
pacman -Rs $(pacman -Qtdq) 删除孤立软件包(递归的,小心用)
pacman -U   abc.pkg.tar.gz      安装下载的abs包,或新编译的本地abc包
pacman-optimize && sync        提高数据库访问速度

输入法fcitx

  按照例子安装fcitx后,还要安装pacman -S fcitx-googlepinyin。  
  配置输入法,在Input Method -> 去掉Only Show Currentt Language勾 -> 搜索Chinese 选择

声音

# pacman -S alsa-utils
# alsamixer
注意要[M] 取消静音

截屏工具scrot

sudo pacman -S scrot
1.抓取整个桌面: scrot ~/Pictures/pic1.jpg
2.抓取窗口: scrot -bs ~/Pictures/pic1.jpg
3.区域截图: scrot -s ~/Pictures/pic1.jpg
4.定时截图: scrot -cd 10 ~/Pictures/pic1.jpg
5.生成缩略图: scrot -t 70% ~/Pictures/pic1.jpg
6.更改截图品质: scrot -q 80 ~/Pictures/pic1.jpg

pyuv的deb安装

archlinux安装deb文件,将deb文件解压后复制

//先解压
ar vx pyuv_0.5-1_x86_64.deb
tar -xzvf data.tar.gz 
//复制
cp usr/bin/pyuv /usr/bin/

运行pyuv出错,pyuv: error while loading shared libraries: libwx_gtk2u_richtext-2.8.so.0: cannot open shared object file: No such file or directory
安装依赖库:pacman -S wxgtk2.8

安装adb

64为系统安装32位程序需要安装库,对/etc/pacman.conf做如下修改

-#[multilib]
-#Include = /etc/pacman.d/mirrorlist
+[multilib]
+Include = /etc/pacman.d/mirrorlist

运行pacman -Sy同步包数据库,安装pacman -S lib32-glibc和pacman -S lib32-libstdc++5; pacman -S lib32-ncurses :lib32-ncurses也安装了,不知是否必须。

串口工具

安装minicom: pacman -S minicom
打开usb转串口:minicom -D /dev/ttyUSB0
设置界面:ctrl+a 后点击o,打开设置界面; ctrl+a后点击l设置保存文件; ctrl+a后z帮助界面

github博客octopress

在Github上搭建Octopress博客

新电脑 老博客

git clone git@github.com:username/username.github.io.git
cd username.github.io
git checkout source
mkdir _deploy
cd _deploy
git init
git remote add origin git@github.com:username/username.github.io.git
git pull origin master
cd ..

下次切换电脑的时候只需要更新一下

#先更新source
git pull origin source
#更新master
cd _deploy
git pull origin master
cd ..