Linux-管道

  • 本文出自svtter.com

  • 头文件: #include

  • 使用方法: int pipe(int chan[2]);
  • 说明: pipe会建立管道,并将文件描述词通过chan返回。一般chan[0]为管道的读取端,chan[1]是写入端。
  • 返回值: 成功返回0,失败返回-1,错误信息保存在errno中
  • 错误信息:
    • EMFILE 进程已用完文件描述词最大量。
    • ENFILE 系统已无文件描述词可用。
    • EFAULT 参数filedes数组地址不合法
/*=============================================================================
#
# Author: svtter - svtter@qq.com
#
# QQ : 57180160
#
# Last modified: 2014-11-21 16:20
#
# Filename: 管道.c
#
# Description: 
#
=============================================================================*/
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
char parent[] = "a message from parent";
char child[] = "a message from child";
int main ()
{
    int p2c[2], c2p[2];
    int pid;
    char buf[100];
    pipe(p2c);
    pipe(c2p);
    pid = fork();
    if(pid > 0)
    {
        close(c2p[0]);
        close(p2c[1]);
        write(c2p[1], parent, sizeof(parent));
        close(c2p[1]);
        read(p2c[0], buf, 100);
        printf("%s\n", buf);
        close(p2c[0]);
    }
    else if(pid == 0)
    {
        close(p2c[0]);
        close(c2p[1]);
        read(c2p[0], buf, 100);
        printf("%s\n", buf);
        write(p2c[1], child, sizeof(child));
        close(c2p[0]);
        close(p2c[0]);
    }
    return 0;
}

运行结果:

管道运行结果

Linux系统函数简介

本文出自svtter.com

系统调用函数说明、参数值及定义

本文摘自老师的资料= =

使用这些函数的时候记得将头文件unistd.h包含到程序中

1、fork()

创建一个新进程
int fork()
其中返回int取值意义如下:
0:创建子进程,从子进程返回的id值大于0:从父进程返回的子进程id值 -1:创建失败

2、lockf(files,function,size):

用作锁定文件的某些段或者整个文件,本函数适用的头文件为:
#include
参数定义:
int lockf(files,function,size)
int files,function;
long size;
其中:files是文件描述符:function是锁定和解锁;1表示锁定,0表示解锁。size是锁定和解锁的字节数,若用0,表示从文件的当前位置到文件尾。

3、msgget(key,flag):

获得一个消息的描述符,该描述符指定一个消息队列以便用于其他系统调用。
该函数使用偷文件如下:
#include
#include
#include
参数定义
int msgget(key,flag)
key_tkey;
int flag;
语法格式:msgqid=msgget(key,flag)
其中:msgid是该系统调用返回的描述符,失败则返回-1;flag 本身由操作允许权和控制命令值相或得到。
如:
IP_CREAT|0400 是否该队列应被创建;
IP_EXCL |0400 是否该队列的创建应是互斥的;等。

msgsnd(id,msgp,size,flag):

发送一消息。
该函数是用头文件如下:
#include
#include
#include
参数定义
int msgnd(id,msgp,size,flag)
int id,size,flag;
struct msgbuf * msgp;
其中:id是返回消息队列的描述符;msgp是指向用户存储区的一个构造体指针,size指示由msgp
指向的数据结构中字符数组的长度;即消息的长度。这个数组的最大值由MSG-MAX系统可调用参数来确
定。flag规定当核心用尽内部缓冲空间时应执行的动作;若在标志flag中末设置IPC_NOWAIT位,则当
41该消息队列中字节数超过一最大值时,或系统范围的消息数超过某一最大值时,调用msgsnd进程睡眠。
若是设置IPC_NOWAIT,则在此情况下,msgsnd立即返回。

msgrcv(id,msgp,size,type,flag):

接受一消息。
该函数调用使用头文件如下:
#include
#include
#include
参数定义
int msgrcv(id,msgp,size,type,flag)
int id,size,type,flag;
struct msgbuf * msgq;
struct sgbuf{long mtpe;chat mtext[];};
语法格式:
count=msgrcv(id,msgp,size,type,flag)
其中:id是用来存放欲接收消息的拥护数据结构的地址;size是msgp中数据数组的大小; type是
用户要读的消息类型:
type为0:接收该队列的第一个消息;
type为正:接收类型type的第一个消息;
type为负:接收小于或等于type绝对值的最低类型的第一个消息。
flag规定倘若该队列无消息,核心应当做什么事,如果此时设置了IPC_NOWAIT标志,则立即返回,
若在flag中设置了MSG_NOERROR,且所接收的消息大小大于size,核心截断所接受的消息。
count是返回消息正文的字节数。

msgctl(id,cmd,buf):

查询一个消息描述符的状态,设置它的状态及删除一个消息描述符。
调用该函数使用头文件如下:
#include
#include
#include
参数定义
int msgctl(id,cmd,buf)
int id,cmd;
struct msgbuf * msgq;
struct msqid_ds * buf;
其中:函数调用成功时返回0,调用不成功时返回-1。id用来识别该消息的描述符;cmd规定命令的
类型。
IPC_START将与id相关联的消息队列首标读入buf。
IPC_SET为这个消息序列设置有效的用户和小组标识及操作允许权和字节的数量。
IPC_RMID删除id的消息队列。
buf是含有控制参数或查询结果的用户数据结构的地址。
附:msgid_ds结构定义如下:
struct msgid_ds
{struct ipc_perm msg_perm; /许可权结构/
shot padl[7];
/由系统使用/
ushort onsg_qnum;
/队列上消息数/
ushort msg_qbytes;
/队列上最大字节数/
42ushort msg_lspid;
/最后发送消息的PID/
ushort msg_lrpid;
/最后接收消息的PID/
time_t msg__stime;
/最后发送消息的时间/
time_t msg_rtime;
/最后接收消息的时间/
me_t msg_ctime;
/最后更改时间/
};
struct ipc_perm
{ushort uid;
/当前用户id/
ushort gid;
/当前进程组id/
ushort cuid;
/创建用户id/
ushort cgid
/创建进程组id/
ushort mode;
/存取许可权/
{shot patl;long pad2} /由系统使用/
};

shmget(key,size,flag):

获得一个共享存储区。
该函数使用头文件如下:
#include
#include
#include
语法格式:
shmid=shmaget(key,size,flag)
参数定义:
int shmaget(key,size,flag)
key_t key;
int size,flag;
其中:size是存储区的字节数,key和flag与系统调用msgget中的参数含义相同。
附:
操作允许权
八进制数
用户可读 00400
用户可读 00200
小组可读 00040
小组可读 00020
其他可读 00004
其他可读 00002
控制命令 值
IPC_CREAT
0001000
IPC_EXCL
0002000
如:shmid=shmget(key,size,(IPC_CREAT|0400));
创建一个关键字为key,长度为size的共享存储区。

shmat(id,addr,flag):

从逻辑上将一个共享存储区附接到进程的虚拟地址空间上。
该函数调用使用头文件如下:
#include
43#include
#include
参数定义:
char * shmat(id,addr,flag)
int id,flag;
char * addr;
语法格式:virtaddr=shmat(id,addr,flag)
其中:id是共享存储区的标识符,addr是用户要使用共享存储区附接的虚地址,若addr是0,系统
是否对应用户规定的地址做舍入操作。如果flag中设置了shm_rnd即表示操作系统在必要时舍去这个地
址。如果设置了shm_rdonly,即表示只允许读操作。viraddr是附接的虚地址。

shmdt(addr):

把一个共享存储区从指定进程的虚地址空间分开。
调用该函数使用头文件:
#include
#include
#include
参数定义:
int shmdt(addr)
char * addr
其中,当调用成功时,返回0值,调用不成功,返回-1,addr是系统调用shmat所返回的地址。
10、shmctl(id,cmd,buf):
对与共享存储区关联的各种参数进行操作,从而对共享存储区进行控制。
调用该函数使用头文件:
#include
#include
#include
参数定义:
int shmctl(id,cmd,buf)
int id,cmd;
struct shmid_ds * buf;
其中:调用成功返回0,否则返回-1。id为被共享存储区的标识符。cmd规定操作的类型。规定如下:
IPC_STAT:返回包含在指定的shmid相关数据结构中的状态信息,并且把它放置在用户存储区中的but
指针所指的数据结构中。执行此命令的进程必须有读取允许权。
IPC_SET:对于指定的shmid,为它设置有效用户和小组标识和操作存取权。
IPC_RMID:删除指定的shmid以及与它相关的共享存储区的数据结构。
SHM_LOCK:在内存中锁定指定的共享存储区,必须是超级用户才可以进行此项操作。
Buf是一个用户级数据结构地址。
附:
shmid_ds
{struct ipc_perm shm_perm;
/
允许权结构/
int shm_segsz;
/
段大小/
int padl;
/
由系统使用;/
ushort shm_lpid;
/
最后操作的进程id;/
ushort shm_cpid;
/
创建者的进程id;/
ushort shm_nattch;
/
当前附界数;/
44short pad2;
/
由系统使用;/
time_t shm_atime;
/
最后附接时间/
time_t shm_dtime;
/
最后段接时间/
time_t shm_ctime;
/
最后修改时间*/
}

signal(sig,function):

允许调用进程控制软中断信号的处理。
头文件为:
#include
参数定义:
signal(sig,function);
int sig;
void(*func)();
其中:sig的值是:
SIGHVP 挂起
SIGINT 键盘按^c键或break键
键盘按quit键
SIGQUIT
SIGILL 非法指令
SIGIOT IOT指令
SIGEMT EMT指令
SIGFPE 浮点运算溢出
SIGKILL 要求终止进程
SIGBUS 总线错
段违例
SIGSEGV
SIGSYS 系统调用参数错
SIGPIPE 向无读者管道上写
闹钟
SIGALRM
软件终结
SIGTERM
用户定义信号
SIGUSRI
第二个用户定义信号
SIGUSR2
SIGCLD 子进程死
SIGPWR电源故障
function的解释如下:
SIG_DEL:缺省操作。对除SIGPWR和SIGCLD外所有信号的缺省操作是进程终结对信号
SIGQUIT,SIGILL,SIGTRA,SIGIOT,SIGEMT,SIGFPE,SIGBUS,SIGSEGV和SIGSYS它产生一内存映
像文件。
SIG_IGN:忽视该信号的出现。
Function:在该进程中的一个函数地址,在核心返回用户态时,它以软中断信号的序号作为参数调用
该函数,对除了信号SIGILL,SIGTRAP和SIGTWR以外的信号,核心自动地重新设置软中断信号处理程序
的值为SIG_DEL,一个进程不能捕获SIGKILL信

python的自动补全

新建python_start_up_file文件

# python startup file
import readline
import rlcompleter
import atexit
import os
# tab completion
readline.parse_and_bind('tab: complete')
# history file
histfile = os.path.join(os.environ['home'], '.pythonhistory')
try:
    readline.read_history_file(histfile)
except ioerror:
    0
atexit.register(readline.write_history_file, histfile)
del os, histfile, readline, rlcompleter

$HOME/.profile文件中写入
export PYTHONSTARTUP=$HOME/.python_start_up_file

小注:

可以使用py3compile来编译文件,然后使用python3+文件名来运行

Python-使用hexo的python脚本

为了简化blog的使用写的python脚本,用来简化自己的操作= =

更新了一下。

最新的代码在coding.net上

#!/usr/bin/env python2
# coding: UTF-8
import sys
import os
# 博客目录
blog_dir = '/home/svitter/svtter.github.io/source/_posts'
def help():
    '''output help information'''
    print '-n: new blog'
    print '-g: Generate and push'
    print '-h: help'
if len(sys.argv) < 2:
    print 'no option'
    help()
else:
    if sys.argv[1].startswith('-'):
        # 改变工作目录
        os.chdir(blog_dir)
        option = sys.argv[1][1:]
        if option == 'n':
            os.system("hexo n " + sys.argv[2])
            os.system("gvim " + sys.argv[2] + ".md")
        elif option == 'g':
            os.system('hexo g')
            os.system('hexo d')
            os.chdir('/home/svitter/svtter.github.io')
            os.system('. update')
        elif option == 'h':
            help()
        elif option == 'dir':
            print blog_dir
        elif option == 'e':
            os.system('gvim ' + blog_dir)
        else:
            print 'no such command.'
    else:
        help()

使用gdb调试

最近都是用gcc+vim写代码,昨天突然写个代码算法出个逻辑bug,因为用了大量递归调用,DEB半天出不来也是醉了,于是

学习一下gdb——之前也是勉强使用过,但是明显感觉不爽阿。。所以这次好好学习,记录一下。

目前我能用到的几个命令:

选择调试文件

  • <shell>: gdb <file>
  • 或者进入gdb以后,使用

断点

显示断点

  • (gdb): info break

添加静态断点

  • (gdb): b[reak] + 行数/函数名 (可以用tab补全)

添加条件断点

条件为真,则在断点处停止
(gdb): b addr if condition

删除断点

删除编号为1的断点, 如果不加参数,会删除所有断点
(gdb): delete breakpoint 1

启用/禁用断点

  • (gdb): disable breakpoint 1
  • (gdb): enable breakpoint 1

运行

开始运行

  • (gdb):r

继续

  • (gdb):c

单步调试

不进入单步执行
(gdb):n
进入的单步
(gdb):s[tep

显示变量

以变量为var为例

输出var的值

  • (gdb):p var

输出上一个求得值

  • (gdb):p

输出历史记录中值

  • (gdb):p $[num]

输出变量的类型

  • (gdb):whatis p

调用函数

  • (gdb):p add(a, b)

数组

输出a后面的十个元素
(gdb):p a@10

设置运行参数

  • (gdb):set args -b -x
  • (gdb):show args

参见大牛的部分:(陈皓的gdb讲解)[http://blog.csdn.net/haoel/article/details/2880]

二、设置观察点(WatchPoint)

观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点:
watch <expr>
    为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。
rwatch <expr>
    当表达式(变量)expr被读时,停住程序。
awatch <expr>
    当表达式(变量)的值被读或被写时,停住程序。
info watchpoints
    列出当前所设置了的所有观察点。

TAG

  • 直接输入<CR>,执行上一条命令

ACM – hdu5104-water

这个题目的总结就是不作不会死- -好端端的暴力我非要用个bfs。

看见自己wrong了还以为是哈希的问题- =

题意

  • p1+p2+p3 = n,$p1 <= p2 <= p3$
  • 输出符合条件的组数

输入输出

  • 给100组n,输出组数

分析

  • 只有3个数,暴力解就可以,注意循环终止条件。

继续阅读

解决无法在CentOS下的gvim中使用ibus输入中文

问题

之前在gvim中一直无法使用中文,格外痛苦,后来使用了vim-ibus插件之后,可以在vim中使用中文了,但是依然不能在gvim中使用,一直以为是两个软件冲突的

问题,现在终于解决了。

  • gvim version: vim-X11
  • ibus version: 1.6

解决方案

  • 问题出在:使用的vim插件中有插件与ibus冲突,但是奈何找不到X11的log(应该可以找到,找到再说。。)
  • 排查方式比较简单,使用:PluginInstall,:PluginClean即可(考虑到我使用vundle管理插件)
  • 去除相应的插件即可(比如现在冲突的是auto-pairs)。如果不想去除冲突插件,可以考虑使用vim-ibus,这个在shell下是可以使得很多冲突减少的。
  • 可能auto-pairs在不久的将来就会修复这个bug,请在具体环境下排查

Linux-进程管理

本文出自svtter.com

进程的创建

用于进程的创建。fork()的作用是,从当前位置创建一个子进程,并执行。fork的返回值为子进程的pid

#include <stdio.h>
void main()
{
    int p1, p2;
    if (p1 = fork()) //父进程返回1, 子进程返回0
        putchar('b');
    else
    {
        if(p2 = fork())
            putchar('c');
        else
            putchar('a');
    }
}

运行结果

运行结果

进程的控制

在这段代码中使用了lockf, 和wait函数。作用是什么呢?

  • lockf顾名思义是锁定file. lockf(1, 1, 0)锁定资源,lockf(1, 0, 0)释放资源。

  • wait作用为等待子进程的返回信息。wait中的signal用于接受进程的返回信号,即exit(0)中的0

#include <stdio.h>
#include <wait.h>
// 利用lockf(1, 1, 0)锁定输出设备
// lockf(1, 0, 0)解锁输出设备
int main()
{
    int p1, p2, i;
    if(p1 = fork())
    {
        lockf(1, 1, 0);
        for(i = 0; i < 500; i++)
            printf("parent%d\n", i);
        lockf(1, 0, 0);
        wait(0);        //confirm the father killed after child
        exit(0);
    }
    else
    {
        if(p2 = fork())
        {
            lockf(1, 1, 0);
            for(i = 0; i < 500; i++)
            printf("son %d\n", i);
            lockf(1, 0, 0);
            wait(0);        //
            exit(0);
        }
        else
        {
            lockf(1, 1,0);
            for(i = 0; i < 500; i++)
                printf("grandchild%d\n", i);
            lockf(1, 0,0);
            exit(0);
        }
    }
}

运行结果

运行结果