my blog my blog

Category: Linux
linux c编程open() read() write()函数的使用方法及实例

 

今天把文件IO操作的一些东东整理下.基本的,对于锁机制下次再整理.常用的文件IO函数有标题的三个open() read() write() .首先打开一个文件使用open()函数,然后可以获取到一个文件描述符,这个就是程序中调用这个打开文件的一个链接,当函数要求到文件描述符fd的时候就把这个返回值给函数即可.read跟write都差不多,格式:read(文件描述符,参数,权限) write(文件描述符,参数,权限),返回值是读取或写入的字符数.其中的权限可以省略,文件描述符就是open()函数的返回值,而参数呢有O_RDONLY(只读) O_WRONLY(只写) O_RDWR(读写) O_CREAT(若不存在则新建) O_TRUNC(若不为空则清空文件)等.对函数想有更多了解可以察看linux下c编程的函数手册.

有些程序还是得自己动手写一下,自己不写就很难知道问题错在哪里,不知道自己是不是真的可以写出来.

写个小例子:文件备份程序

功能:输入一个"文件名",将生成"文件名.backup"的备份文件.若输入量超过两个或者无输入量,报错,若文件不存在或无权限,报错.成功返回提示.

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <string.h> 
  4. #include <fcntl.h> 
  5.  
  6. int main(int argc,char *args[]) { 
  7.     char buff[1024]; 
  8.     int fd1,fd2,i; 
  9.     int baksize = sizeof(args[1])+7; 
  10.     char bakfile[baksize]; 
  11. // input one file only 
  12.     if(argc != 2){ 
  13.         printf("Input one file a time!\n"); 
  14.         exit(1); 
  15.     } 
  16. //bakfile="XXX.backup"设置备份文件名称 
  17.     strcpy(bakfile,args[1]); 
  18.     strcat(bakfile,".backup"); 
  19. //open() 
  20.     fd1 = open(args[1],O_RDONLY,0644); 
  21.     fd2 = open(bakfile,O_RDWR|O_CREAT|O_TRUNC); 
  22.     if((fd1 < 0)||(fd2 < 0)){ 
  23.         printf("Open Error!Check if the file is exist and you have the permission!\n"); 
  24.         exit(1); 
  25.     }  
  26. //read from fd1 and write buff to fd2 
  27.     while((i = read(fd1,buff,sizeof(buff))) > 0) { 
  28.     write(fd2,buff,i);//这里需要用读取到的字符数,否则会出错,因为buff数组有可能未被全覆盖 
  29.     } 
  30.     close(fd1); 
  31.     close(fd2); 
  32.     printf("Backup done!\n"); 
  33.     exit(0); 
  34.      

 

linux c编程main函数的参数以及带参实例

 

写c程序,让用户一次又一次的输入参数输入回车是很不友好也很不明智的方法.所以为了更好的用户体验,参数应该可以在执行程序的时候直接就可以把参数都设定完成.好吧,说下main函数的参数.

一般我们就给main两个参数,写成如下形式:

main (int argc,char *argv[])

其中argc是统计的参数个数,默认为1.因为执行文件的文件名就是一个参数.

理所当然,argv[0]也是默认就有的,内容就是文件名.

当然,这个argc跟argv是可以更换为其它名称的,只要数据类型对就ok的.

解释这些估计就了解了个差不多了.然后直接看个实例就应该可以理解了.

实例:调用wget来下载一个文件.要求可以直接输入下载地址,如果输入两个参数则报错,提示使用方法:

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <unistd.h> 
  4.  
  5. int main (int argc,char *args[]){ 
  6.     if(argc > 2){ 
  7.     printf("Error input!\nUsages:wget [http/ftp url]\n"); 
  8.     exit(1); 
  9.     } 
  10.     char *url = args[1]; 
  11.     printf("The URL is:%s\n",url); 
  12.     execlp("wget","wget","-c",url,NULL); 
  13.     exit(0); 

 

linux下daemon守护进程的编写实例

 

对于daemon守护进程,可能大多数朋友了解不多.对于守护进程,也就是说它由init直接来管理.举个例子:当我们打开一个terminal,输入gedit,然后编辑一些字,不要关闭gedit,这时候回到终端terminal,按ctrl+c,这时候你看到了什么,gedit关闭了对不对.因为gedit可以看成是一个进程哇,而且这时候终端并没有显示$或者#,结束的肯定是gedit的进程哇.如果我们想让这些进程在我们的后台运行,不受到terminal的限制,就需要来写一个daemon守护进程了.

这里说一下具体的方法:

1.fork()一个子进程

2.把父进程exit(0)退出,这时候子进程成为了一个孤立的进程,由init接管

3.setsid(),脱离控制终端,登录会话和进程组

介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号 (PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。 控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使 进程成为会话组长.当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。

4.close(i) ,关闭文件描述符

进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。

5.umask(0);重置文件权限掩码

6.更改当前的工作目录chdir(),这个可选

ok,这样子一个daemon就差不多了.

下面写了一个编程的实例,用wget 后台执行一个下载,然后把下载信息记录到info.txt文件中以便察看下载结果.

 

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <string.h> 
  4. #include <fcntl.h> 
  5. #include <sys/types.h> 
  6. #include <sys/wait.h> 
  7. #include <unistd.h> 
  8.  
  9. int main(){ 
  10.     pid_t daemon; 
  11.     int i,fd; 
  12.      
  13.     daemon = fork(); 
  14.     if(daemon < 0){ 
  15.         printf("Fork Error!"); 
  16.         exit(1); 
  17.     } 
  18.     else if (daemon > 0 ) { 
  19.         printf("Father process exited!"); 
  20.         exit(0); 
  21.     } 
  22.     setsid(); 
  23.     umask(0); 
  24.     for (i = 0;i < getdtablesize();i++){ 
  25.         close(i); 
  26.     } 
  27.     system("wget -c http://cdimage.ubuntu.com/daily-live/current/quantal-desktop-amd64.iso >info.txt 2>&1"); 
  28.     exit(0); 
  29.  

 

linux c编程信号处理的一些实例signal sigaction

 

 刚接触linux下的c编程,记录一下吧.对于信号,就是我们经常用的那个kill,kill可以发送很多信号,当然,我们也可以通过程序来实现,我们甚至可以来定义对于不同的信号的处理,比如ctrl+c可能并不能退出我们的程序,因为我们可以监视ctrl+c发送的SIGINT信号,并且用我们自己的功能来进行处理.PS:发现写代码也是个需要手感的事儿,意识到该多看看vim的配置鸟~~~自动不全一定要强大才行哇~~~

先把课本上的两个小实例放上来,记录下:

1.signal()的使用

捕捉ctrl+c发送的SIGINT与ctrl+\发送的SIGQUIT信号

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <signal.h> 
  4.  
  5. void my_func(int sign_no) { 
  6.     if (sign_no == SIGINT) { 
  7.         printf("I have get SIGINT\n"); 
  8.     } else if (sign_no == SIGQUIT) { 
  9.         printf("I have get SIGQUIT\n"); 
  10.     } 
  11.  
  12. int main() { 
  13.     printf("waiting for signal SIGINT or SIGQUIT ... \n"); 
  14.     signal(SIGINT, my_func); 
  15.     signal(SIGQUIT, my_func); 
  16.     pause(); 
  17.     exit(0); 

2.sigaction()的使用<—感觉是signal的一个变种

同样是捕捉ctrl+c发送的SIGINT与ctrl+\发送的SIGQUIT信号

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <signal.h> 
  4.  
  5. void my_func(int sign_no) { 
  6.     if (sign_no == SIGINT) { 
  7.         printf("I have get SIGINT\n"); 
  8.     } else if (sign_no == SIGQUIT) { 
  9.         printf("I have get SIGQUIT\n"); 
  10.     } 
  11.  
  12. int main() { 
  13.     struct sigaction action; 
  14.     printf("waiting for signal SIGINT or SIGQUIT ... \n"); 
  15.     action.sa_handler = my_func; 
  16.     sigemptyset(&action.sa_mask); 
  17.     action.sa_flags = 0; 
  18.     sigaction(SIGINT, &action, 0); 
  19.     sigaction(SIGQUIT, &action, 0); 
  20.     pause(); 
  21.     exit(0); 

3.信号集

默认对信号进行状态阻塞,此时输入任何信号都不执行,ctrl+c 与ctrl+\都不会被执行,但是当输入任意字符并回车后,原来的信号就会被立即执行.可以先输入任意字符解除SIG_BLOCK状态,然后执行SIG_INT与SIG_QUIT,SIG_INT调用我们自己的函数my_func,所以程序会一直不退出,但是SIG_QUIT仍旧是系统的函数,因此可以正常表达

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <sys/types.h> 
  4. #include <unistd.h> 
  5. #include <signal.h> 
  6.  
  7. void my_func(int signum) { 
  8.     printf("If you want to quit ,please try SIGQUIT\n"); 
  9.  
  10. int main() { 
  11.     sigset_t set, pendset; 
  12.     struct sigaction action1, action2; 
  13.  
  14.     if (sigemptyset(&set) < 0) { 
  15.         perror("sigemptyset"); 
  16.         exit(1); 
  17.     } 
  18.  
  19.     if (sigaddset(&set, SIGQUIT) < 0) { 
  20.         perror("sigaddset"); 
  21.         exit(1); 
  22.     } 
  23.  
  24.     if (sigaddset(&set, SIGINT) < 0) { 
  25.         perror("sigaddset"); 
  26.         exit(1); 
  27.     } 
  28.  
  29.     if (sigismember(&set, SIGINT)) { 
  30.         sigemptyset(&action1.sa_mask); 
  31.         action1.sa_handler = my_func; 
  32.         action1.sa_flags = 0; 
  33.         sigaction(SIGINT, &action1, 0); 
  34.     } 
  35.  
  36.     if (sigismember(&set, SIGQUIT)) { 
  37.         sigemptyset(&action2.sa_mask); 
  38.         action2.sa_handler = SIG_DFL; 
  39.         action2.sa_flags = 0; 
  40.         sigaction(SIGQUIT, &action2, 0); 
  41.     } 
  42.  
  43.     if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) { 
  44.         perror("sigprocmask"); 
  45.         exit(1); 
  46.     } else { 
  47.         printf("Signal set was blocked,Press any key!"); 
  48.         getchar(); 
  49.     } 
  50.     if (sigprocmask(SIG_UNBLOCK, &set, NULL) < 0) { 
  51.         perror("sigprocmask"); 
  52.         exit(1); 
  53.     } else { 
  54.         printf("Signal set is unblock state\n"); 
  55.     } 
  56.     while (1) 
  57.         ; 
  58.     exit(0); 

 

Linux C编程—fork子程序以及fifo有名管道的使用

 

写一个程序,创建一个fifo有名管道,然后利用程序与子程序完成程序间的信息传输实例.

功能:输入什么,输出什么

           输入q或者Q程序退出

调用fifo文件:/tmp/fifo

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <unistd.h> 
  4. #include <sys/types.h> 
  5. #include <sys/stat.h> 
  6. #include <errno.h> 
  7. #include <fcntl.h> 
  8. #include <limits.h> 
  9.  
  10. #define FIFO_FILE "/tmp/fifo" 
  11. #define BUFFER_SIZE PIPE_BUF 
  12.  
  13. int main(void) { 
  14.     char buff[BUFFER_SIZE]; 
  15.  
  16.     if (access(FIFO_FILE, F_OK) == -1) { 
  17.         if ((mkfifo(FIFO_FILE, 0666) < 0) && (errno != EEXIST)) { 
  18.             printf("Filo file create error!\n"); 
  19.         } 
  20.     } 
  21.     pid_t newfork = fork(); 
  22.     if (newfork < 0) { 
  23.         printf("Fork error!\n"); 
  24.         exit(1); 
  25.     } else if (newfork == 0) { 
  26.         int fd1 = open(FIFO_FILE, O_RDONLY); 
  27.         int reader; 
  28.         if (fd1 < 0) { 
  29.             printf("child process fd error!\n"); 
  30.             exit(1); 
  31.         } 
  32.         while (1) { 
  33.             reader = read(fd1, buff, BUFFER_SIZE); 
  34.             if ((buff[0] == 'q' && buff[1] == '\0'
  35.                     || (buff[0] == 'Q' && buff[1] == '\0')) { 
  36.                 printf("Get EXIT message and quit!\n"); 
  37.                 close(fd1); 
  38.                 exit(0); 
  39.             } 
  40.             if (reader > 0) { 
  41.                 printf("Read from FIFO:%s\n", buff); 
  42.             } 
  43.         } 
  44.     } else { 
  45.         int fd2 = open(FIFO_FILE, O_WRONLY); 
  46.         int writer; 
  47.         if (fd2 < 0) { 
  48.             printf("Father process fd error!\n"); 
  49.             exit(1); 
  50.         } 
  51.         while (1) { 
  52.             if ((buff[0] == 'q' && buff[1] == '\0'
  53.                     || (buff[0] == 'Q' && buff[1] == '\0')) { 
  54.                 close(fd2); 
  55.                 exit(0); 
  56.             } 
  57.             scanf("%s", buff); 
  58.             writer = write(fd2, buff, BUFFER_SIZE); 
  59.         } 
  60.     } 

 

分享Ubuntu Linux鼠标主题TheCandyman2

 

今天为大家分享的是奶牛比较喜欢的一款鼠标主题TheCandyman的第二版TheCandyman2.鼠标主题的效果可以看下图:

ubuntu鼠标主题 linux鼠标主题

主题的安装也很简单.下载TheCandyman2的压缩包,解压缩后执行

sudo cp -r TheCandyman02 /usr/share/icons/

即可正常安装.然后设置启用鼠标主题即可.

点此下载TheCandyman2 linux鼠标主题

Ubuntu12.04桌面指南离线中文版下载

 

今天微博上看到有网友已经做好了Ubuntu12.04桌面指南离线版,并且提供了下载,奶牛也就借花献佛也转过来了。记得去年的时候奶牛也自己把ubuntu10.10的桌面指南做成了离线版(虽然官方后来也出了),感兴趣想知道如何做到的,可以man wget获取详细的介绍,wget有r选项可以递归,还有转换为本地链接的选项,很强大哦。

废话又说多了,这个Ubuntu12.04桌面指南奶牛也大体看了一下,还是比较适合桌面用户的,大部分你可能遇到的问题在这里都可以找到合理的解释与提供的方法,新踏入ubuntu阵营的朋友还是可以好好学习一下的。

文件下载好后直接打开index.html阅读即可。Ubuntu12.04桌面指南离线中文版下载

在线阅读可以访问:http://people.ubuntu.com/~happyaron/ubuntu-docs/precise-html/

最近奶牛也想做个ubuntu wiki,个人不是很喜欢ubuntu官方的那个,感觉索引不够清晰,还是更喜欢arch的wiki风格。打算启用新域名www.ubuntuo.com ,也就是友帮拓啦,不知道朋友们有什么好建议,或者哪些比较好用的wiki架构可以推荐给奶牛。

 

动态磁盘无法写入grub问题介绍

 

昨天帮小远装linux,发现正常安装后grub无法写入,而且最强大的是mbr中的windows引导还顽强的存在。当时分区的时候就感觉怪怪的,因为没有主分区跟扩展分区,刚开始也没多想,只是觉得怪怪的,后来经过很久的排错,终于知道了,原来是由于windows的动态磁盘造成的。

查了下百科,介绍如下:Windows 2000起引入了基本磁盘和动态磁盘的概念,并且把它们添加到Windows系统管理员的工具之中。无论是基本磁盘还是动态磁盘,你都可以使用任何文件系统,包括FAT和NTFS。而且你可以在动态磁盘改变卷而不需要重启系统。你可以把一个基本磁盘转换 成动态磁盘。但是你必须了解这并不是一个双向的过程。一旦你从基本磁盘变成了动态磁盘,除非你重新创建卷,否则你不能将它转变回去。

我们平时用的是基本磁盘,有主分区跟扩展分区之分,而动态磁盘默认都是简单卷,还有其它的卷模式。这里我们就不讨论了,我们只要知道这个grub无法写入的问题是由于动态磁盘造成的就ok鸟。

看了网上的一些文章,其实是有无损把动态磁盘转换为基本磁盘的程序跟方法的,但是这里只是针对简单卷的哦,有其它卷的就不好处理了。

资料我已经都整理到文件中了,朋友们有需要的可以直接下载无损转换动态分区工具包 (请先备份数据再使用,以防万一)

教程可以看下图:点击可以看大图

怎么无损数据地转换动态磁盘到基本磁盘

 

Ubuntu12.04新手入门指南

写一篇新手入门指南吧,可能总结的不够全面,再补充吧~有些点可能写的不够明确,希望朋友们可以好好借助google baidu等搜索引擎来寻找更详细的介绍.

1.系统安装

对于Ubuntu系统的安装,方法真的很多.比如在windows下就可以进行的wubi安装,正常推荐的光盘安装(哪里有光盘?自己把iso镜像文件刻录为光盘就可以了哇),U盘安装以及奶牛前篇介绍过的硬盘安装.如果采用wubi方式安装,请尽量将系统放在一个ntfs分区上,否则可能会因为文件大小限制造成一些问题.奶牛更推荐的是直装方式,但是需要你有一定的了解跟基础.

Ubuntu的安装,你首先要了解linux下的分区以及引导方式的一些知识,奶牛在这里简单的说一下:

Ubuntu等linux操作系统一般不要求你安装在主分区上,不像windows要求那样子苛刻,就算全是逻辑分区也是没有任何问题的.一般对于新手,分配一个分区给根目录(/)+一个交换分区(swap).交换分区的概念也许在windows下并没有怎么被提到,不过如果你了解比较多,一定听说过页面缓存文件,一个跟交换分区差不多的东西,都是用作交换时候用的,弥补内存不足造成的一些问题,就相当于一个速度不高的内存区域,一般设置为内存的1~1.5倍,不过内存超过4G的PC就可以不设置了.

引导呢,linux主流系统现在都是用grub来做引导,此处所说的grub是grub2,从前几个版本就开始一直在用,因为使用Ubuntu的grub引导可以轻松实现对于windows的引导,所以一般我们都选择由grub来做引导,如果安装完成后发现没有windows的开机启动选项,可以直接执行命令update-grub来寻找windows的引导的.

2.配置工具ubuntu-tweak

对于一个操作系统,配置很关键,如果你已经顺利的安装完成,那么就要用一些配置工具来帮你配置好一个你更习惯更喜欢的桌面环境了.这里奶牛首推的是ubuntu-tweak.国人编写,功能较为完善的ubuntu配置工具,涵盖了从系统桌面环境配置到源的修改,以及垃圾清理.使用ubuntu-tweak几乎可以完成对于ubuntu的常用配置,如果你还觉得不够过瘾,想对于特效有更详细的配置,可以使用ccsm,compiz的高级配置工具.

3.驱动问题

驱动问题估计是个老大难,因为奶牛只有一台Y450笔记本,没有遇到太大问题,除了此次六屏幕问题(已经解决),并没有遇到过其它问题.不过奶牛没遇到并不代表其他朋友不会遇到,这里奶牛说一下.显卡驱动一般分为开源驱动跟闭源驱动,奶牛一般直接去官方网站下载官方驱动(也就是闭源驱动,总体性能上还是不错的),对于显卡驱动的安装,一般会下载一个.run的驱动,然后关闭lightgdm服务,sh xxx.run来安装驱动.如果你用开源驱动没啥问题,就继续用也没关系的.

声音驱动一般用alsa来配置就可以搞定的.而无线网卡呢,linux下有一个可以安装windows无线驱动的工具ndiswrapper,如果无线无法搞定可以试试这个工具.

4.软件

牛X的应用程序,linux下很多都有相应的版本,如果没有,也会有很多功能类似的替代软件可以使用.比如office有open office 跟libre office,现在永中跟wps也加入到linux环境下的office工具开发当中了.

影音播放只要解码没啥问题也都可以正常使用,一般装个vlc,装个totem+gstream那个系列的解码就ok搞定99%了.

上网呢,mozilla firefox chrome opera等各种主流浏览器也都完美支持.

一些拨号的客户端可以通过wine的方法来搞定.

IM软件:QQ可以直接用webQQ,skype有linux的客户端,功能很强大,gtalk哇msn哇可以直接用自带的集成软件去实现.

更多软件尽在:ubuntu的软件中心

5.建议买本书学起

可以看奶牛的介绍文章:Ubuntu Linux 入门书籍教程推荐

6.一些思想

开放:不要局限在windows的点点鼠标,你应该更加深入了解系统

共享:把好的东西分享给需要的人

自由:让自己充满想法,要geek一些,不要被局限

友帮拓:虽然很多人说这个中文名很烂,但是奶牛觉得它的含义很明确:友好互爱,互帮互助,开拓进取

Ubuntu12.04正式版下载已经开放

 

News一则,Ubuntu12.04正式版已经可以下载了.

Ubuntu12.04 i386下载:

http://releases.ubuntu.com/12.04/ubuntu-12.04-desktop-i386.iso

Ubuntu12.04 amd64下载:

http://releases.ubuntu.com/12.04/ubuntu-12.04-desktop-amd64.iso

Ubuntu12.04 server下载:

http://releases.ubuntu.com/12.04/ubuntu-12.04-server-i386.iso

http://releases.ubuntu.com/12.04/ubuntu-12.04-server-amd64.iso

Wubi程序下载:

http://releases.ubuntu.com/12.04/wubi.exe

Ubuntu12.04的综合评价还是很不错的,希望各位linux爱好者可以尝试使用,奶牛会在近期发布一系列新手入门指导,敬请关注咯~~~

点此添加奶牛博客到您的订阅