【发布时间】:2017-10-03 19:12:33
【问题描述】:
在以下代码中:
FILE *cmd = popen("pidof -s gst-launch-0.10", "r");
字符串“pidof -s gst-launch-0.10”将存储在进程地址空间中的什么位置。我在堆栈中没有看到它..
添加整个代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define TRUE 1
#define FALSE 0
#define VS_STREAMER_ON 1
#define VS_STREAMER_OFF 2
#define VS_VIDSIG_ON 3
#define VS_VIDSIG_OFF 4
#define VS_VSIG_BL_OFF 5
typedef int bool;
bool bVidSignal, bVidSignalOld = FALSE;
int iVidState = VS_STREAMER_OFF;
bool IsStreamerRunning();
bool stopStreamer();
bool startStreamer();
bool ShowNoSignal()
{
printf("\nShowNoSignal()\n");
system("dd if=/home/TDS/DiskOnChip/nosig.bmp of=/dev/fb0");
return TRUE;
}
bool GetVideoSignal()
{
char buffer[10];
memset(buffer, '\0', 10);
int fd = open("/sys/bus/i2c/devices/1-000f/sysstatus", O_RDONLY, 0);
//int fd = open("/sys/bus/i2c/drivers/tc358743_mipi/1-000f/sysstatus", O_RDONLY, 0);
if (fd > 0)
{
read(fd, buffer, sizeof(buffer));
if (strlen(buffer) > 0)
{
long val = strtoul(buffer, NULL, 16);
close(fd);
if (val == 0x8F)
{
return TRUE;
}
else
{
return FALSE;
}
}
}
else
{
printf("GetVideoSignal(): can't open file\n");
}
return FALSE;
}
void CheckVideoState(void)
{
//static int iRestartCnt = 0;
static int iAppCheckTic = 60; // To Run for the first time
static int iVideoOn = FALSE;
static int iGstreamerStartCount = 0;
static int iGstreamerStartAttempt = 0;
static int iGstreamerStopCounter = 0;
bVidSignal = GetVideoSignal();
if ( (bVidSignal) && (bVidSignalOld) )
{
iVideoOn = TRUE;
printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld);
}
else if ( (!bVidSignal) && (!bVidSignalOld) )
{
iVideoOn = FALSE;
printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld);
}
else
{
printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld);
}
bVidSignalOld = bVidSignal;
switch (iVidState)
{
case VS_STREAMER_OFF:
if ( iVideoOn )
{
iGstreamerStartCount = 0;
iGstreamerStartAttempt = 0;
printf("CheckVideoState():VS_STREAMER_OFF: Signal ON\n");
iVidState = VS_VIDSIG_ON;
}
else
{
iAppCheckTic++;
if ( iAppCheckTic >= 60 )
{
iAppCheckTic = 0;
iGstreamerStartCount = 0;
iGstreamerStartAttempt = 0;
if ( IsStreamerRunning() )
{
printf("CheckVideoState():VS_STREAMER_OFF: Killing Gstreamer\n");
stopStreamer();
sleep(1);
ShowNoSignal();
}
}
}
break;
case VS_VIDSIG_ON:
if ( iGstreamerStartAttempt > 5 )
{
printf("CheckVideoState():calling Reboot after 5 Gstreamer Restarts!\n");
//SystemExit(SS_REBOOT);
system("reboot");
}
if ( iGstreamerStartCount == 0 )
{
if ( IsStreamerRunning() )
{
iGstreamerStopCounter = 0;
iVidState = VS_VIDSIG_OFF;
printf("CheckVideoState():VS_VIDSIG_ON: GStreamer Running Already Switch to VS_VIDSIG_OFF\n");
}
else
{
startStreamer();
printf("CheckVideoState():VS_VIDSIG_ON: Starting GStreamer\n");
iGstreamerStartCount++;
iGstreamerStartAttempt++;
}
}
if ( iGstreamerStartCount >= 10 )
{
if ( IsStreamerRunning() )
{
iVidState = VS_STREAMER_ON;
printf("CheckVideoState(): VS_VIDSIG_ON: GStreamer Running After %d Seconds, Switching to VS_STREAMER_ON\n", iGstreamerStartCount);
}
else
{
iGstreamerStartCount = 0;
printf("CheckVideoState(): VS_VIDSIG_ON: GStreamer Not Running After 5 Seconds, Clearing iGstreamerStartCount\n");
}
break;
}
iGstreamerStartCount++;
break;
case VS_STREAMER_ON:
if ( iVideoOn )
{
if ( !IsStreamerRunning() )
{
iGstreamerStartCount = 0;
iGstreamerStartAttempt = 0;
printf("CheckVideoState():VS_STREAMER_ON: Gstreamer Not running even after video signal available\n");
}
}
else
{
iVidState = VS_VIDSIG_OFF;
printf("CheckVideoState():VS_STREAMER_ON: Lost Video Signal\n");
iGstreamerStopCounter = 0;
}
break;
case VS_VIDSIG_OFF:
if ( IsStreamerRunning() )
{
stopStreamer();
printf("CheckVideoState():VS_VIDSIG_OFF: Killing GStreamer\n");
}
else
{
if ( iGstreamerStopCounter >= 3 )
{
iVidState = VS_STREAMER_OFF;
printf("CheckVideoState():VS_VIDSIG_OFF: Switching to VS_STREAMER_OFF after 3 seconds\n");
break;
}
}
iGstreamerStopCounter++;
break;
}
}
pid_t GetStreamerPID()
{
pid_t pid = 0;
char line[100];
memset(line, '\0', 100);
FILE *cmd = popen("pidof -s gst-launch-0.10", "r");
if ( cmd == NULL )
{
printf("Cmd Null\n");
}
fgets(line, 100, cmd);
if (strlen(line) > 0)
{
pid = strtoul(line, NULL, 10);
}
pclose(cmd);
return pid;
}
bool IsStreamerRunning()
{
pid_t pid = GetStreamerPID();
if (pid > 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
void MainLoop()
{
while(1)
{
sleep(1);
CheckVideoState();
}
}
bool startStreamer()
{
char command[256];
pid_t pid = GetStreamerPID();
if (pid > 0)
{
}
else
{
sprintf(command, "gst-launch imxv4l2src ! imxv4l2sink &");
printf("StartStreamer: command=[%s]\n", command);
system(command);
}
return TRUE;
}
bool stopStreamer()
{
char command[256];
pid_t pid = GetStreamerPID();
if (pid > 0)
{
sprintf(command, "kill %d", pid);
printf("StopStreamer: command=[%s]\n", command);
system(command);
}
else
{
}
return TRUE;
}
int main()
{
MainLoop();
return 0;
}
代码因分段错误而崩溃,这发生在 CheckVideoState() 案例 VS_VIDSIG_ON 的 IsStreamerRunning() 函数中...注意。这是随机发生的。通过gdb进行调试,回溯在popen时停止,它正在访问不允许访问的内存。因此分段错误。谁能帮帮我..
添加 gdb 回溯:
Breakpoint 1, 0x76ea6ffc in popen@@GLIBC_2.4 () from /lib/libc.so.6
#0 0x76ea6ffc in popen@@GLIBC_2.4 () from /lib/libc.so.6
#1 0x00010d14 in GetStreamerPID () at getPid.c:243
#2 0x00010d98 in IsStreamerRunning () at getPid.c:263
#3 0x00010aac in CheckVideoState () at getPid.c:157
#4 0x00010dd4 in MainLoop () at getPid.c:284
#5 0x00010efc in main () at getPid.c:358
Program received signal SIGSEGV, Segmentation fault.
0x80808080 in ?? ()
(gdb) bt
#0 0x80808080 in ?? ()
#1 0x76ee1b70 in fork () from /lib/libc.so.6
#2 0x76ea6d80 in _IO_proc_open@@GLIBC_2.4 () from /lib/libc.so.6
#3 0x76ea704c in popen@@GLIBC_2.4 () from /lib/libc.so.6
#4 0x00010d14 in GetStreamerPID () at getPid.c:243
#5 0x00010d98 in IsStreamerRunning () at getPid.c:263
#6 0x00010aac in CheckVideoState () at getPid.c:157
#7 0x00010dd4 in MainLoop () at getPid.c:284
#8 0x00010efc in main () at getPid.c:358
我从上周开始调试,使用 valgrind, gdb ,我不知道它为什么要从内存中访问地址
【问题讨论】:
-
当你说进程地址空间时,你指的是哪个进程?父母还是孩子?
-
而不是定义
line然后赋值,你可以在定义处初始化:char line[100] = {0};。 -
parent...我在使用这个函数时遇到了一个奇怪的问题。它在 popen 随机抛出分段错误...任何人都可以猜到可能是什么问题..
-
@pmg 您的解决方案和 OP 的当前代码用零填充所有 100 个字节。但是,这样做没有意义,因为 OP 继续告诉 fgets() 覆盖缓冲区。如果你想“安全”(因为你懒得去检查 fgets 的返回值),你只需要写一个 NUL 终止符:
line[0] = '\0'; -
嗨 Jonathon.. 我已经添加了我的整个代码,它通过抛出分段错误随机崩溃.. 当它从 IsStreamerRunning() 调用 popen API 时会发生这种情况。在 VS_VIDSIG_ON 的情况下
标签: c linux process operating-system gdb