现在的位置: 首页 > 综合 > 正文

Linux命令SYSTEM()启动命令注意事项

2018年04月18日 ⁄ 综合 ⁄ 共 1763字 ⁄ 字号 评论关闭
system是一个使用简单,设计复杂的程序。
它主要包含fork exec waitpid三个步骤。
下来我来还原楼主的错误:
程序A:
/* socksrv.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> /* for struct sockaddr_in*/

#define BACKLOG 10
#define MYPORT  4000

int main()
{
  char *addr;
  int sockfd;
  int new_fd;
  struct sockaddr_in my_addr, their_addr;

  int res;
  int sin_size;

  char *buf;
  /* 取得套接字描述符*/
  sockfd = socket(AF_INET,     /* domain*/
                  SOCK_STREAM, /* type*/
                  0);          /* protocol*/

  if (sockfd == -1) {
    perror("socket");
    exit(1);
  }

  /* Init sockaddr_in */
  my_addr.sin_family = AF_INET;                /* 注意: 应使用主机字节顺序*/
  my_addr.sin_port = htons(MYPORT);            /* 注意: 应使用网络字节顺序*/
  my_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* 使用自己的 IP 地址 */
  bzero(&(my_addr.sin_zero), 8);               /* 结构的其余的部分须置 0*/

  /* 指定一个套接字使用的地址及端口*/
  res = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr));
  if (res == -1) {
    perror("bind");
    exit(1);
  }

  /* 监听请求, 等待连接*/
  res = listen(sockfd,
               BACKLOG);  /* 未经处理的连接请求队列可容纳的最大数目*/               
  if (res == -1) {
    perror("listen");
    exit(1);
  }
system("./hello&");
  /* 接受对方的连接请求, 建立连接,返回一个新的连接描述符.
   * 而第一个套接字描述符仍在你的机器上原来的端口 listen()
   */
  sin_size = sizeof(struct sockaddr_in);
  new_fd = accept(sockfd, (void *)&their_addr, &sin_size);

  buf = (char *)malloc(255);
  if (buf == NULL) {
    printf("malloc failed\n");
    exit(1);
  }
  
  /* 接受对方发来的数据*/
  res = recv(new_fd, buf, 255, 0);
  if (res == -1) {
    perror("recv()");
    exit(1);
  }

  /* 关闭本次连接*/
  close(new_fd);

  /* 关闭系统监听*/
  close(sockfd);

  printf("recv data:%s\n", buf);
  free(buf);
  return 0;
}
程序B:hello,在主程序中用system("./hello&)调用。
#include <stdlib.h>
int main(){
    while(1){
        sleep(1000);
    }
return 0;
}
编译后运行程序A。我们可以在其它终端窗口看到 ./A ./hello正在运行,netstat -a 看到,tcp 4000端口被 占用。
我们用Ctrl+c中断程序A模拟楼主的崩溃操作。
这时,再在其它终端窗口看看,./A没有了。./hello还在运行。netstat -a看到。4000端口还在占用。
这时再次运行./A,提示bind: Address already in use而退出。
情况就是这样。
因为执行system时,系统会fork一个A的子进程,再去执行B.
当你的A崩溃以后,它的一个子进程实际上还在运行,它打开的端口,文件,等还在使用。
所以再次运行A时,由于自定的互斥机制而退出。
如:再次绑定端口时提示端口已在使用。
杀死B后,A的子进程结束,它的资源释放,所以才能再次运行A。
我建议楼主使用exec系列函数来启动B。

抱歉!评论已关闭.