tag 标签: 进程

相关博文
  • 热度 22
    2015-7-18 09:11
    1195 次阅读|
    0 个评论
    在 Linux/Uinx 编程中,对进程的创建经常使用 fork 函数,但 SylixOS 中并不支持 fork 函数,因而传统的 fork()+exec() 创建进程的模式不再适用。虽然嵌入式应用中多线程的使用远远多于多进程的使用,但如果不能够实现进程创建显然会感觉缺点什么。 考虑到 SylixOS 声称支持 POSIX1003.1b 标准,除了 fork 函数外,还有 posix_spawn 函数可以选择。此函数及相关函数的介绍在网络中不多见,无意间看到 QNX 操作系统的文档 http://www.qnx.com/developers/docs/660/index.jsp?topic=%2Fcom.qnx.doc.neutrino.lib_ref%2Ftopic%2Fp%2Fposix_spawn.html 中有详细说明(这里非常感谢 QNX 能够毫无保留的开放帮助文档)。这个文档里面几乎介绍了所有常用的 POSIX 函数,而且条理清晰。 弄明白相关函数功能和参数后,使用就相对简单了,代码如下: #include spawn.h #include stdio.h #include errno.h #include unistd.h #include sys/types.h #include sys/wait.h extern char **environ; /************************************************************************ ** 函数名称: main ** 功能描述: 程序主函数 ************************************************************************/ int main(int argc, char * argv = {"hello","-l",NULL};     posix_spawnattr_t          attr;     posix_spawn_file_actions_t fact;     posix_spawnattr_init(attr);             /*  初始化spawn函数参数 */     posix_spawn_file_actions_init(fact);     istatus = posix_spawn(pid,"./helloworld",fact,attr,                                                     args,environ);        if(istatus != 0) {          printf("child process create faile");     }     printf("pid=%d,child pid = %d\n",getpid(),pid);/*  输出子父进程ID  */     sunpid = waitpid(pid,stat,0);                 /*  等待子进程结束  */     printf("%d stat is %d\n",sunpid,stat);、     exit(0);     return 0; }
  • 热度 16
    2012-10-20 20:02
    1156 次阅读|
    0 个评论
          守护进程,也就是通常说的Daemon进程,   在linux   系统的引导的时候会开启很多服务,这些服务就叫做守护进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件,在系统关闭时终止。   守护进程是脱离于终端并且在后台运行的进程。大多数服务都是通过守护进程实现的,同时,守护进程还能完成许多系统任务,例如,作业规划进程crond、打印进程lqd等(这里的结尾字母d就是Daemon的意思)。 由于在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。但是守护进程却能够突破这种限制,它从被执行开始运转,直到整个系统关闭时才退出。如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就必须把这个进程变成一个守护进程。            各种版本的Unix的实现机制不尽相同,造成不同Unix环境下守护进程的编程规则并不一致。这需要读者注意,照搬某些书上的规则(特别是BSD4.3和低版本的System V)到Linux会出现错误的。守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由用户终端(通常是shell)执行。总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。     守护进程编程步骤: 1. 在后台运行。         为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。 if(pid=fork()) exit(0);//是父进程,结束父进程,子进程继续 2. 脱离控制终端,登录会话和进程组         有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。 控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长: setsid(); 说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。 3. 禁止进程重新打开控制终端         现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端: if(pid=fork()) exit(0);//结束第一子进程,第二子进程继续(第二子进程不再是会话组长) 4. 关闭打开的文件描述符         进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们: for(i=0;i 关闭打开的文件描述符close(i); 5. 改变当前工作目录         进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如/tmpchdir("/") 6. 重设文件创建掩模         进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0); 7. 处理SIGCHLD信号         处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。 signal(SIGCHLD,SIG_IGN); 这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。  守护进程实例         守护进程实例包括两部分:主程序test.c和初始化程序init.c。主程序每隔一分钟向/tmp目录中的日志test.log报告运行状态。初始化程序中的init_daemon函数负责生成守护进程。读者可以利用init_daemon函数生成自己的守护进程。 1. init.c清单 #include unistd.h #include signal.h #include sys/param.h #include sys/types.h #include sys/stat.h void init_daemon(void) {        int pid;        int i;        if(pid=fork())                exit(0);//是父进程,结束父进程        else if(pid 0)                exit(1);//fork失败,退出                            //是第一子进程,后台继续执行        setsid();//第一子进程成为新的会话组长和进程组长        //并与控制终端分离        if(pid=fork())               exit(0);//是第一子进程,结束第一子进程        else if(pid 0)               exit(1);//fork失败,退出                           //是第二子进程,继续                           //第二子进程不再是会话组长         for(i=0;i NOFILE;++i)//关闭打开的文件描述符               close(i);         chdir("/tmp");//改变工作目录到/tmp         umask(0);//重设文件创建掩模         return; } 2. test.c清单 #include stdio.h #include time.h void init_daemon(void);//守护进程初始化函数 main() {       FILE *fp;       time_t t;       init_daemon();//初始化为Daemon       while(1)//每隔一分钟向test.log报告运行状态       {              sleep(60);//睡眠一分钟              if((fp=fopen("test.log","a")) =0)              {                    t=time(0);                    fprintf(fp,"Im here at %s/n",asctime(localtime(t)) );                    fclose(fp);               }        } } 以上程序在RedHat Linux6.0下编译通过。步骤如下: 编译:gcc -g -o test init.c test.c 执行:./test 查看进程:ps -ef 从输出可以发现test守护进程的各种特性满足上面的要求。     linux守护进程列表     amd:自动安装NFS( 网络文件系统 )守侯进程   apmd:高级电源治理   Arpwatch:记录日志并构建一个在LAN接口上看到的以太网地址和ip地址对数据库   Autofs:自动安装治理进程automount,与NFS相关,依靠于NIS   Bootparamd:引导参数服务器,为LAN上的 无盘工作站 提供引导所需的相关信息   crond:linux下的计划任务   Dhcpd:启动一个DHCP(动态IP地址分配)服务器   Gated: 网关 路由守候进程,使用动态的OSPF 路由选择协议   Httpd:WEB服务器   Inetd:支持多种 网络服务 的核心守候程序   Innd:Usenet新闻服务器   Linuxconf:答应使用本地WEB服务器作为 用户接口 来配置机器   Lpd: 打印服务器   Mars-nwe:mars-nwe文件和用于Novell的打印服务器   Mcserv:Midnight命令 文件服务器   named:DNS服务器   netfs:安装NFS、Samba和NetWare网络文件系统   network:激活已配置网络接口的脚本程序   nfs:打开NFS服务   nscd:nscd(Name Switch Cache daemon)服务器,用于NIS的一个支持服务,它高速缓存用户口令和组成成员关系   portmap:RPC portmap治理器,与inetd类似,它治理基于RPC服务的连接   postgresql:一种SQL 数据库服务器   routed:路由守候进程,使用动态RIP路由选择协议   rstatd:一个为LAN上的其它机器收集和提供系统信息的守候程序   ruserd: 远程用户 定位服务,这是一个基于RPC的服务,它提供关于当前记录到LAN上一个机器日志中的用户信息   rwalld:激活rpc.rwall服务进程,这是一项基于RPC的服务,答应用户给每个注册到LAN机器上的其他终端写消息    rwho d:激活rwhod服务进程,它支持LAN的rwho和ruptime服务   sendmail: 邮件服务器 sendmail   smb:Samba文件共享/打印服务   snmpd:本地简单网络治理候进程   squid:激活代理服务器squid   syslog:一个让系统引导时起动syslog和klogd 系统日志 守候进程的脚本   xfs:X Window字型服务器,为本地和远程X服务器提供字型集   xntpd:网络时间服务器   ypbind:为NIS(网络信息系统)客户机激活ypbind服务进程   yppasswdd:NIS口令服务器   ypserv:NIS主服务器   gpm:管鼠标的   identd:AUTH服务,在提供用户信息方面与finger类似   守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。(部分资料来自于网络) 大多数服务都是通过守护进程实现的,同时,守护进程还能完成许多系统任务,例如,作业规划进程crond、打印进程lqd等(这里的结尾字母d就是Daemon的意思)。    它是一个      盘生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程常常在系统引导装入时启动,在系统关闭时终止。   它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程常常在系统引导装入时启动,在系统关闭时终止。   它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程常常在系统引导装入时启动,在系统关闭时终止。                 
  • 热度 19
    2012-4-9 10:52
    1821 次阅读|
    0 个评论
    之前写了无名管道方式的通信,这里就验证下有名管道的通信方式。 有名管道他和普通文件一样可以被读写,而且实际存在于存储设备中,一般也即磁盘,但是有名管道在进程结束后通信的信息就自动消失了,而一般的文件在进程结束后信息是不会变的。 这里也依然y用按键和LED做验证。 按键和LED的模块连接: LED:http://bbs.ednchina.com/BLOG_ARTICLE_3002404.HTM 按键:http://bbs.ednchina.com/BLOG_ARTICLE_3002953.HTM 以下贴上实际的应用程序: #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/ioctl.h #include fcntl.h #define FIFO "/tmp/tmp1/fifo_test" int main(int argc, char **argv) {     pid_t pid;     int fd_key;     int fd_led;     int fd_fifo;     int val;     int i;     int press_cnt ={0,0,0,0,0,0};     int press_cnt_tmp ={0,0,0,0,0,0};     unlink(FIFO);  //如果存在先删除他     if((mkfifo(FIFO,0744))==-1) {      perror("mkfifo error\n");      exit(EXIT_FAILURE);     }     pid = fork();     if(pid==-1) {     printf("fork error \n");     exit(EXIT_FAILURE);     }     else if(pid==0) {      fd_led = open("/dev/s3c6410leds",0);      if(fd_led0) {      printf("open led error\n");      exit(EXIT_FAILURE);      }      printf("open led succeed\n");      while(1) {      fd_fifo=open(FIFO,O_RDONLY);      read(fd_fifo,press_cnt_tmp,sizeof(press_cnt_tmp));      close(fd_fifo);      if(press_cnt_tmp ) { ioctl(fd_led,1,0); printf("in child:key1 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,1,1); printf("in child:key2 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,1,2); printf("in child:key3 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,1,3); printf("in child:key4 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,0,3); printf("in child:key5 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,0,1); printf("in child:key6 pressed\n"); }      }     }     else {     fd_key = open("/dev/keyint",0);     if(fd_key0) {     printf("open key error\n");     exit(EXIT_FAILURE);     }      printf("open key succeed\n");      while(1) {       val = read(fd_key,press_cnt,sizeof(press_cnt));       if(val0) {       printf("read error\n");       exit(EXIT_FAILURE);       }             for(i=0;i6;i++) {          if(press_cnt )          printf("In parent:KEY%d pressed %d times\n",(i+1),press_cnt );                 }         fd_fifo=open(FIFO,O_WRONLY);       write(fd_fifo,press_cnt,sizeof(press_cnt));       close(fd_fifo);      }     }     unlink(FIFO);     return 0; }   编译之后就可以放到目标板上运行验证,实验的现象依然是按键按下会有相应的LED动作。                
  • 热度 23
    2012-4-9 10:51
    1888 次阅读|
    0 个评论
    最近开始学了linux应用编程,懂了点多进程的基础知识,便跃跃欲试,想立即应用起来,以加深印象,学任何东西重在实践,技术尤为如此。 在linux中创建新的进程的函数为fork(),如果成功返回0,如果失败返回-1。这是分叉的意思,比较形象的比喻。在一个进程进行过程中有多了个进程便岔开两道(或者多道),而新建的进程与之前创建这个进程的进程为父子关系,事实上这个新建的进程是和原来的父进程几乎一摸一样的,这是站在数据以及栈空间大小角度上而言的,只是子进程会跑到新的栈空间去运行。而且这对父子进程是完全独立的,所以数据在各自的进程中改变都互不影响。要想互传信息就需要进程间通信。这也是这篇文章所要做的事情,验证进程间通信的方式。 这里要验证的是无名管道(pipe)的通信,这种通信方式只使用与亲属关系进程间的通信,形象的说是在亲属间打通一个管道进行数据传输。 那么之前我是写了led和按键驱动的,所以直接可以用上之前的驱动。 按键和LED的模块连接: LED:http://bbs.ednchina.com/BLOG_ARTICLE_3002404.HTM 按键:http://bbs.ednchina.com/BLOG_ARTICLE_3002953.HTM 以下我直接贴出应用程序代码: #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/ioctl.h int main(int argc, char **argv) {     pid_t pid;     int fd_key;     int fd_led;     int val;     int i;     int press_cnt ={0,0,0,0,0,0};     int press_cnt_tmp ={0,0,0,0,0,0};     int pipedes ; //创建管道     if((pipe(pipedes))==-1) {     perror("create pipe wrong\n");     exit(EXIT_FAILURE);     }     pid = fork();     if(pid==-1) {     printf("fork error \n");     exit(EXIT_FAILURE);     }     else if(pid==0) {      fd_led = open("/dev/s3c6410leds",0);      if(fd_led0) {      printf("open led error\n");      exit(EXIT_FAILURE);      }      printf("open led succeed\n");      while(1) {      if((read(pipedes ,press_cnt_tmp,sizeof(press_cnt)))==-1)      {       perror("child read error\n");       exit(EXIT_FAILURE);      }      if(press_cnt_tmp ) { ioctl(fd_led,1,0); printf("in child:key1 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,1,1); printf("in child:key2 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,1,2); printf("in child:key3 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,1,3); printf("in child:key4 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,0,3); printf("in child:key5 pressed\n"); }      if(press_cnt_tmp ) { ioctl(fd_led,0,0); printf("in child:key6 pressed\n"); }      }     }     else {     fd_key = open("/dev/keyint",0);     if(fd_key0) {     printf("open key error\n");     exit(EXIT_FAILURE);     }      printf("open key succeed\n");      while(1) {      val = read(fd_key,press_cnt,sizeof(press_cnt));            if(val0) {       printf("read error\n");       exit(EXIT_FAILURE);       }        for(i=0;i6;i++) {          if(press_cnt )          printf("In parent:KEY%d pressed %d times\n",(i+1),press_cnt );                 }         if((write(pipedes ,press_cnt,sizeof(press_cnt)))==-1)       {       perror("parent write error \n");       exit(EXIT_FAILURE);       }      }     }     return 0; }        无名管道通信原理: 然后编译成应用程序就可以放到目标板上运行了,按下按键,LED会做相应的动作。
  • 热度 17
    2011-10-27 09:54
    1232 次阅读|
    0 个评论
    Andrew Armutat 产品市场部 吉时利仪器公司   2601 型单通道系统源表            2602 型双通道系统源表   作为SMU的程序存储器和测试序列发生器如何加速测试进程的例子,吉时利仪器公司研究了对一个单通道SMU进行编程,内部执行一个典型源-测量序列的情形。然后将该测试序列与通过PC的GPIB总线控制的同样功能的测试进行比较。 测试序列由对 二极管 的三个简单测试组成:Vf,Vbr和Ir。首先,用Visual Basic写好PC 测试程序,通过GPIB总线控制SMU,执行这三项测试,并在VB程序中作出测试/失效判断;并将所有的SMU读数都通过GPIB总线返回到PC中。这种提供PC控制的系统完成二极管测试并作出通过/失效判断的时间约为250ms。 接下来,采用SMU内置测试序列的功能进行测试。 PC 程序 将预先配置仪器一次,然后进行源-测量测试过程,作出通过/失效判断,控制元器件分选处理器,所有这些操作都将有SMU在其内部进行,独立于PC和 GPIB总线 。这种方法可在约25ms的时间内完成测试,也就是说,它比前面的方法要快10倍。元器件分选处理器处理一个器件大约180ms,因此,使用SMU测试序列发生器可获得52%的产量增长率。在元器件的生产应用中,这将有效地降低一半的测试成本。 在上面描述的单通道系统中,使用测试序列发生器是一种直接有效的解决方法。如果对两个或更多通道的系统,配置测试序列发生器和管理多个触发器将变得极其复杂。但是,带有测试脚本处理器和高速控制总线的新型SMU可解决此问题,具有方便快捷地调整系统容量、具有可伸缩性和简单的编程特性。这些特性具有共享所有SMU的资源运行复杂、高速测试序列的能力。 (见本文其它部分有关吉时利2601型和2602型系统源表的说明) 登录吉时利官方微博( http://weibo.com/keithley )与专家进行互动,还可以免费索取WB/263: 免费索取《数据采集、测量与控制手册》哦~( http://www.keithley.cn/LLM/land/llm/ ) 2601型单通道系统源表http://www.keithley.com.cn/products/localizedproducts/currentvoltage/2601 2602  http://www.keithley.com.cn/products/localizedproducts/currentvoltage/2602 854X通信激光二极管配架http://www.keithley.com.cn/products/localizedproducts/opto/85428544 PC程序http://www.keithley.com.cn/products/localizedproducts/currentvoltage/4500mts GPIB总线http://www.keithley.com.cn/products/dcac/specialtysystems/optoelectronics/?mn=SYSTEM25
相关资源