分享
 
 
 

Linux程式设计之三

王朝system·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

Linux程式设计-12.目录操作

http://www.openchess.org/noitatsko/programming/ (2001-05-26 10:08:00)

Linux下的目录是依照标准来实作的,因此,您可以毫无问题地移殖到任何其它UNIX平台。

--------------------------------------------------------------------------------

getcwd/getwd : 取得目前所在目录

--------------------------------------------------------------------------------

#include

char * getcwd(char *buf,size_t size);

buf将会返回目前路径名称。

任何的错误发生,将会返回NULL。如果路径长度超过size,errno为ERANGE。getcwd返回的值永远是没有symbol link的。

--------------------------------------------------------------------------------

#include

char *getwd(char *buf);

getwd是个危险的函数,一般都会强烈建议不要用,因为您无法确定最长的目录长度为多少。PATH_MAX定义了最长的路径长度。在Linux下所以提供这个函数主要是因为「传统」。

--------------------------------------------------------------------------------

chdir/fchdir/chroot : 改变目前所在目录

--------------------------------------------------------------------------------

#include

int chdir(const char * pathname);

int fchdir(int fd);

chdir根据pathname变更目前的所在目录,它只改变该程式的所在目录。

fchdir根据已开启的fd(file descriptor)目录来变更。

--------------------------------------------------------------------------------

#include

int chroot(const char * path);

chroot改变该程式的根目录所在。例如chroot("/home/ftp")会将根目录换到/home/ftp下,而所有档案操作都不会超出这个围内。为保障安全性,当chdir("/..")时,将会仅切换到chdir("/"),如此便不会有档案安全问题。

--------------------------------------------------------------------------------

mkdir/rmdir : 造/移除目录

--------------------------------------------------------------------------------

#include

#include

int mkdir(const char * dirname,mode_t mode);

mkdir会造一个新目录出来,例如mkdir("/home/foxman",0755);。

如果该目录或档案已经存在,则操作失败。

--------------------------------------------------------------------------------

#include

int rmdir(char * pathname);

这个函数移除pathname目录。

--------------------------------------------------------------------------------

opendir/readdir/closedir/rewinddir : 读取目录资讯

--------------------------------------------------------------------------------

#include

DIR * opendir(const char * pathname);

int closedir(DIR *dir);

struct dirent * readdir(DIR *dir);

int rewinddir(DIR *dir);

struct dirent {

long d_ino; /* inode number */

off_t d_off; /* offset to this dirent */

unsigned short d_reclen; /* length of this d_name */

char d_name [NAME_MAX+1]; /* file name (null-terminated) */

};

opendir开启一个目录操作DIR,closedir关闭之。

readdir则循序读取目录中的资讯,rewinddir则可重新读取目录资讯。

以下是个标准例。

--------------------------------------------------------------------------------

#include

#include

char ** dirGetInfo(const char *pathname)

{

char ** filenames;

DIR * dir;

struct dirent * ent;

int n = 0;

filenames = (char **)malloc(sizeof(char*));

filenames[0]=NULL;

dir = opendir(pathname);

if (!dir) return filenames;

while ((ent = readdir(dir))) {

filenames = (char**)realloc(filenames,sizeof(char*)*(n+1));

filenames[n] = strdup(ent->d_name);

n++;

}

closedir(dir);

filenames = (char **)realloc(filenames,sizeof(char*)*(n+1));

filenames[n] = NULL;

return filenames;

}

Linux程式设计-13.记忆体对映mmap

http://www.openchess.org/noitatsko/programming/ (2001-05-26 11:00:00)

Linux允许将档案对映到记忆体空间中。如此可以产生一个在档案资料及记忆体资料一对一的对映,例如字型档的存取。使用记忆体对映有许多好处:

高速档案存取。一般的I/O机制通常需要将资料先到缓区中。记忆体对映免去了中间这一层,加速档案存取速度。

可执行档可对映到记忆体空间中,使程式动态载入。Linux Dynamic Loading便是如此实作出来的。

新的记忆体可以透过利用/dev/zero来产生全零的档案。

新的记忆体可以用於执行目的,这对解译式编译器非常有用。

可把档案当成记忆体来用,直接使用指标来操作。

对映的记忆体可当成行程间共享记忆体,该记忆体内容存在档案中,因此与行程无关。

--------------------------------------------------------------------------------

页对齐「Page Alignment」

#include

size_t getpagesize(void);

系统记忆体通常被分割成页的单位。在Intel及SPARC上,每页为4096 Bytes(4K),在Alpha上则为8192 Bytes(8K)。getpagesize返回该系统的页大小。

--------------------------------------------------------------------------------

#include

#include

void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);

int munmap(void *start, size_t length);

mmap开启记忆体对映。

start指定记忆体位置,通常都是用NULL。offset指定档案要在那里开始对映,通常都是用0。

protections

PROT_READ

PROT_WRITE

PROT_EXEC

PROT_NONE

flags

MAP_FIXED

MAP_PRIVATE

MAP_SHARED

MAP_ANONYMOUS

MAP_DENYWRITE

MAP_GROWSDOWN

MAP_LOCKED

munmap关闭记忆体对映。

--------------------------------------------------------------------------------

int msync(const void *start, size_t length, int flags);

如果开启记忆体对映是希望写入档案中,那麽修改过的记忆体会在一段时间内与档案稍稍有点不同。如果您希望立即将资料写入档案中,可使用msync。

start为记忆体开始位置,length为长度。

flags则有三个:

MS_ASYNC : 请Kernel快将资料写入。

MS_SYNC : 在msync结束返回前,将资料写入。

MS_INVALIDATE : 让核心自行决定是否写入,仅在特殊状况下使用。

--------------------------------------------------------------------------------

int mlock(const void *addr, size_t len);

int munlock(const void *addr, size_t len);

锁住记忆体,仅root有权限这样做。

--------------------------------------------------------------------------------

int mlockall(int flags);

锁住所有记忆体空间。

MCL_CURRENT : 所有的记忆页都会被锁住。

MCL_FUTURE : 所有的新增的记忆页都会被锁住。

int munlockall(void);

Linux程式设计-14.动态函数库

http://www.openchess.org/noitatsko/programming/ (2001-05-26 12:10:00)

--------------------------------------------------------------------------------

本节说明Linux下动态函数库的使用及设计。

大多数大型的UNIX软体都会将许多个别的部份拆开来设计,通常这些部份被称为「plugins」或「modules」。它们会用许多方式来结合,如「pipe」、「IPC」或「shared objects」。

Linux下的Dynamic Linking Loader介面标准来自於Solaris。

在Dynamic Linking的操作方式下,所有的函数及资料变数都被称为「symbol」,要使用时,需要透过dlsym来找出其实际位址。

--------------------------------------------------------------------------------

所有动态函数载入的函数均宣告在中,共有四个函数。

void *dlopen (const char *filename, int flag);

const char *dlerror(void);

void *dlsym(void *handle, char *symbol);

int dlclose (void *handle);

--------------------------------------------------------------------------------

dlopen()的作用为寻找函数库档案,开启它、并做一些初始化的动作。

filename如果以"/"符号开始,dlopen()将不会搜寻该函数库的路径,否则它将会透过以下方式搜寻档案:

透过LD_LIBRARY_PATH所指定的路径搜寻

/etc/ld.so.cache所指定的路径。该档案是由ldconfig所产生,其设定位於/etc/ld.so.conf。

找寻/usr/lib及/lib两个内定目录。

flag有三个:

RTLD_GLOBAL : 在函数库中的变数内定是不输出的。指定RTLD_GLOBAL可输出这些变数。

RTLD_LAZY : 当函数被执行时,才找出所使用的变数对照表。

RTLD_NOW : 当函数被载入时,立刻找出所使用的变数对照表。

RTLD_GLOBAL可与RTLD_LAZY或RTLD_NOW结合,RTLD_LAZY及RTLD_NOW不可同时使用。

--------------------------------------------------------------------------------

dlerror()返回最近发生的错误讯息,如果没有错误发生,那麽将会返回NULL。

--------------------------------------------------------------------------------

dlsym()载入所指定的函数。

--------------------------------------------------------------------------------

dlclose()关闭开启的函数库。它会检查一个对照计数,将开启的函数库次数数量减一,如果为零,则关闭该函数库。

--------------------------------------------------------------------------------

hellodl

--------------------------------------------------------------------------------

hello.so的设计

Linux程式设计-15.同步I/O多重处理

http://www.openchess.org/noitatsko/programming/ (2001-05-26 13:04:00)

同步I/O多重处理(Synchronous I/O Multiplexing)

--------------------------------------------------------------------------------

当我们在同时间需要处理许多I/O时,例如网路伺服器socket,有时候一个一个处理,程式非常难写,这时候可以利用select来达成。

--------------------------------------------------------------------------------

#include

#include

#include

int select(int n, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

FD_CLR(int fd, fd_set *set);

FD_ISSET(int fd, fd_set *set);

FD_SET(int fd, fd_set *set);

FD_ZERO(fd_set *set);

FD_ZERO清除所有fd_set。

FD_SET将fd加入fd_set中。

FD_CLR将fd从fd_set中移除。

FD_ISSET检查fd是否属於该fd_set。

struct timeval {

int tv_sec;

int tv_usec;

};

Linux程式设计-16.TarBall

http://www.openchess.org/noitatsko/programming/ (2001-05-26 14:08:00)

我写了一个targz的函数库,专门处理档案安装的事宜,这个函数库在我写的X Corona Package Installer中使用到。它与zlib一起使用。

targz.h

targz.c

--------------------------------------------------------------------------------

typedef struct {

char name[100];

char mode[8];

char uid[8];

char gid[8];

char size[12];

char mtime[12];

char chksum[8];

char typeflag;

char linkname[100];

char magic[6];

char version[2];

char uname[32];

char gname[32];

char devmajor[8];

char devminor[8];

char prefix[155];

} TarEntry;

GNU Tar档案格式

--------------------------------------------------------------------------------

typedef struct {

char * Package;

char * FileName;

char * path;

gzFile fp;

int size;

int totalsize;

int expanding;

int mode;

int result;

TarEntry ** NAME;

} TarBall;

--------------------------------------------------------------------------------

TarBall * tgzOpen(char * Filename,char * mode);

开启一个tarball档,档名为Filename。

mode

"r":为读取模式。

"w":为写入模式。

--------------------------------------------------------------------------------

int tgzLookup(TarBall * tgz);

撷取tarball内档案资讯。

--------------------------------------------------------------------------------

int tgzClose(TarBall * tgz);

关闭tarball档。

--------------------------------------------------------------------------------

int tgzExpand(TarBall * tgz);

解开档案。

--------------------------------------------------------------------------------

int tgzSkip(TarBall * tgz);

跳过下一个档案,不安装。

--------------------------------------------------------------------------------

int tgzAppend(TarBall * tgz,char *FileName);

新增档案到tarball中,必须要是Write Mode

Linux程式设计-17.SVGALIB

http://www.openchess.org/noitatsko/programming/ (2001-05-26 15:00:00)

SvgaLib是Linux Console下的VGA驱动函数库。虽然它的品质还是有点低,支援的萤幕卡种类不算太多,但是有许多的游戏及程式都是用它来做开发,可以算是非官方的标准了。如果您准备要在Console下撰写图形功能的程式,目前来说SVGALIB是您唯一的选择。目前使用SVGALIB的程式有许多,中文终端机使用SVGALIB的就有a4c.tty/yact/bcs16。

这里我只讲一些简单的使用方法,如启动vga及mouse的使用。要有效地、高阶的运用,技巧杂很多,例如a4c.tty就另外往上架一层Star Window Manager,来管理一个小型视窗系统。

--------------------------------------------------------------------------------

vga

vgamouse

--------------------------------------------------------------------------------

int vga_setmode(int mode);

int vga_hasmode(int mode);

int vga_setpalette(int index, int red, int green, int blue);

int vga_getpalette(int index, int *red, int *green, int *blue);

int vga_setcolor(int color);

int vga_drawpixel(int x, int y);

int vga_drawline(int x1, int y1, int x2, int y2);

int vga_getpixel(int x, int y);

vga_modeinfo *vga_getmodeinfo(int mode);

unsigned char *graph_mem;

unsigned char *vga_getgraphmem(void);

void vga_setpage(int p);

void vga_setreadpage(int p);

void vga_setreadpage(int p);

void vga_setwritepage(int p);

void vga_setdisplaystart(int a);

void vga_waitretrace(void);

int vga_init(void);

int vga_setrgbcolor(int r, int g, int b);

--------------------------------------------------------------------------------

#define TEXT 0 /* Compatible with VGAlib v1.2 */

#define G320x200x16 1

#define G640x200x16 2

#define G640x350x16 3

#define G640x480x16 4

#define G320x200x256 5

#define G320x240x256 6

#define G320x400x256 7

#define G360x480x256 8

#define G640x480x2 9

#define G640x480x256 10

#define G800x600x256 11

#define G1024x768x256 12

#define G1280x1024x256 13 /* Additional modes. */

#define G320x200x32K 14

#define G320x200x64K 15

#define G320x200x16M 16

#define G640x480x32K 17

#define G640x480x64K 18

#define G640x480x16M 19

#define G800x600x32K 20

#define G800x600x64K 21

#define G800x600x16M 22

#define G1024x768x32K 23

#define G1024x768x64K 24

#define G1024x768x16M 25

#define G1280x1024x32K 26

#define G1280x1024x64K 27

#define G1280x1024x16M 28

#define G800x600x16 29

#define G1024x768x16 30

#define G1280x1024x16 31

#define G720x348x2 32 /* Hercules emulation mode */

#define G320x200x16M32 33 /* 32-bit per pixel modes. */

#define G640x480x16M32 34

#define G800x600x16M32 35

#define G1024x768x16M32 36

#define G1280x1024x16M32 37

/* additional resolutions */

#define G1152x864x16 38

#define G1152x864x256 39

#define G1152x864x32K 40

#define G1152x864x64K 41

#define G1152x864x16M 42

#define G1152x864x16M32 43

#define G1600x1200x16 44

#define G1600x1200x256 45

#define G1600x1200x32K 46

#define G1600x1200x64K 47

#define G1600x1200x16M 48

#define G1600x1200x16M32 49

typedef struct {

int width;

int height;

int bytesperpixel;

int colors;

int linewidth; /* scanline width in bytes */

int maxlogicalwidth; /* maximum logical scanline width */

int startaddressrange; /* changeable bits set */

int maxpixels; /* video memory / bytesperpixel */

int haveblit; /* mask of blit functions available */

int flags; /* other flags */

/* Extended fields: */

int chiptype; /* Chiptype detected */

int memory; /* videomemory in KB */

int linewidth_unit; /* Use only a multiple of this as parameter for set_displaystart */

char *linear_aperture; /* points to mmap secondary mem aperture of car

int aperture_size; /* size of aperture in KB if size>=videomemory.

void (*set_aperture_page) (int page);

/* if aperture_size void *extensions; /* points to copy of eeprom for mach32 */

/* depends from actual driver/chiptype.. etc. */

} vga_modeinfo;

Linux程式设计-18.Dialog (1)前言

http://www.openchess.org/noitatsko/programming/ (2001-05-26 17:04:00)

dialog是个shell scripts用的,事实上当您下载Linux Kernel时,里面有个scripts/lxdialog目录,其实那就是dialog原始码,只是Linux kernel为了避免与原有dialog相突,将名字修改为lxdialog。当您使用"make menuconfig"时,便是在用dialog这套工具。另外,Slackware的安装程式,事实上也是用dialog这套工具来做界面的。

您可以利用shell script来呼叫dialog,也可以利用perl来呼叫它,用以提供较友善的使用者界面。

利用dialog这个工具,您可以在不需要写"艰深"的ncurses的程式的状况下,使用Shell Script,完成很杂的操作界面,大大减少产品开发时间。

Linux程式设计-19.gpm

http://www.openchess.org/noitatsko/programming/ (2001-05-27 12:10:00)

gpm是Linux console下的滑鼠驱动程式,它主要提供文字模式下的滑鼠事件处理。Linux下文字界面的滑鼠几乎都是用gpm来处理。

gpm的文件在gpm原始码的doc目录中,详细的说明可参考该目录中的文件gpm programming guide,此处只提供给您KickStart的一些技巧及一些参考说明。

特别注意到以下的例,需在console下执行,不可在X Window的 Terminal下执行。

--------------------------------------------------------------------------------

例 : gpm_mouse.c

gpm原始码中有一个mev.c的程式,主要用来测试滑鼠状态。事实上,mev.c是个很好的例,本例便是取自mev.c,经过简化修改而来。

#include

#include

#include

#include

void main(int argc,char **argv)

{

fd_set readset;

Gpm_Event event;

Gpm_Connect conn;

conn.eventMask = ~0;

conn.defaultMask = ~GPM_HARD;

conn.maxMod = 0;

conn.minMod = 0;

if (Gpm_Open(&conn,0)==-1) {

printf("Can not open mouse connection

");

exit(1);

}

while (1) {

FD_ZERO(&readset);

FD_SET(gpm_fd,&readset);

select(gpm_fd+1,&readset,0,0,0);

if (FD_ISSET(gpm_fd,&readset)) {

if (Gpm_GetEvent(&event)>0) {

printf("mouse: event 0x%02X, at %2i %2i (delta %2i %2i),"

"button %i, modifiers 0x%02X

",

event.type,

event.x,event.y,

event.dx,event.dy,

event.buttons,

event.modifiers

);

}

}

}

while (Gpm_Close());

}

编译

gcc -o gpm_mouse gpm_mouse.c -lgpm

检验结果

mouse: event 0x01, at 15 1 (delta -2 -1),button 0, modifiers 0x00

mouse: event 0x01, at 14 1 (delta -1 0),button 0, modifiers 0x00

mouse: event 0x01, at 13 1 (delta -1 0),button 0, modifiers 0x00

--------------------------------------------------------------------------------

资料结构

typedef struct Gpm_Connect {

unsigned short eventMask, defaultMask;

unsigned short minMod, maxMod;

int pid;

int vc;

} Gpm_Connect;

enum Gpm_Etype {

GPM_MOVE=1,

GPM_DRAG=2, /* exactly one of the bare ones is active at a time */

GPM_DOWN=4,

GPM_UP= 8,

GPM_SINGLE=16, /* at most one in three is set */

GPM_DOUBLE=32,

GPM_TRIPLE=64, /* WARNING: I depend on the values */

GPM_MFLAG=128, /* motion during click? */

GPM_HARD=256, /* if set in the defaultMask, force an already used event to pass over to another handler */

GPM_ENTER=512, /* enter event, user in Roi's */

GPM_LEAVE=1024 /* leave event, used in Roi's */

};

typedef struct Gpm_Event {

unsigned char buttons, modifiers; /* try to be a multiple of 4 */

unsigned short vc;

short dx, dy, x, y;

enum Gpm_Etype type;

int clicks;

enum Gpm_Margin margin;

} Gpm_Event;

typedef int Gpm_Handler(Gpm_Event *event, void *clientdata);

函数宣告

int Gpm_Open(Gpm_Connect * CONN, int FLAGS);

int Gpm_Close(void);

int Gpm_GetEvent(Gpm_Event * EVENT);

int Gpm_Getc(FILE * fp);

#define Gpm_Getchar() Gpm_Getc(stdin)

int Gpm_Wgetch();

#define Gpm_Getch() (Gpm_Wgetch(NULL))

int Gpm_Repeat (int millisecs);

int Gpm_DrawPointer (int X, int Y, int FD);

int GPM_DRAWPOINTER (Gpm_Event *EPTR;)

int Gpm_FitValuesM (int *X, int *Y, int MARGIN);

int Gpm_FitValues (X,Y);

Gpm_FitEvent (EPTR);

char *Gpm_GetLibVersion (int *where);

char *Gpm_GetServerVersion (int *where);

int Gpm_GetSnapshot (Gpm_Event *ePtr);

Linux程式设计-20.getopt

http://www.openchess.org/noitatsko/programming/ (2001-05-27 13:04:00)

getopt在UNIX下的命令列程式特别好用,特别是在你有许多参数要加入时。一般来说,你可以透过「man 3 getopt」来获得其说明。

--------------------------------------------------------------------------------

int getopt(int argc, char * const argv[],const char *optstring);

extern char *optarg;

extern int optind, opterr, optopt;

--------------------------------------------------------------------------------

例:这个例是从manpage抄出来的,蛮不清处的。我会再找时间写一系列例。

#include

int

main (argc, argv)

int argc;

char **argv;

{

int c;

int digit_optind = 0;

while (1)

{

int this_option_optind = optind ? optind : 1;

int option_index = 0;

static struct option long_options[] =

{

{"add", 1, 0, 0},

{"append", 0, 0, 0},

{"delete", 1, 0, 0},

{"verbose", 0, 0, 0},

{"create", 1, 0, 'c'},

{"file", 1, 0, 0},

{0, 0, 0, 0}

};

c = getopt_long (argc, argv, "abc:d:012",

long_options, &option_index);

if (c == -1)

break;

switch (c)

{

case 0:

printf ("option %s", long_options[option_index].name);

if (optarg)

printf (" with arg %s", optarg);

printf ("

");

break;

case '0':

case '1':

case '2':

if (digit_optind != 0 && digit_optind != this_option_optind)

printf ("digits occur in two different argv-elements.

");

digit_optind = this_option_optind;

printf ("option %c

", c);

break;

case 'a':

printf ("option a

");

break;

case 'b':

printf ("option b

");

break;

case 'c':

printf ("option c with value `%s'

", optarg);

break;

case 'd':

printf ("option d with value `%s'

", optarg);

break;

case '?':

break;

default:

printf ("?? getopt returned character code 0%o ??

", c);

}

}

if (optind < argc)

{

printf ("non-option ARGV-elements: ");

while (optind < argc)

printf ("%s ", argv[optind++]);

printf ("

");

}

exit (0);

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有