当前位置:Linux教程 - Linux资讯 - Linux程式设计之三

Linux程式设计之三

  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);
[1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 

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);
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 

如果开启记忆体对映是希望写入档案中,那麽修改过的记忆体会在一段时间内与档案稍稍有点不同。如果您希望立即将资料写入档案中,可使用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
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 

-------------------------------------------------------------------------------- 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":为写入模式。 --------------------------------------------------------------------------------
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 

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
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 

#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)
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 

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 */
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 

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'},
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 

{"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); }

(出处:http://www.sheup.com)


上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9]