C - 在 1021 次迭代时出现段错误,在 1020 次迭代时无法打开 i2c



嗨,使用以下脚本将数据连续记录到.csv文件时遇到问题

int ddm(void)
{   
//  96 Temp MSB,    97 Temp LSB,    98 Vcc MSB,     99 Vcc LSB
//  100 TX_BIA MSB, 101 TX_BIA LSB,
//  102 TX MSB,     103 TX LSB,     104 RX MSB,     105 RX LSB

FILE *focat;
float temperature, vcc, tx_bias, optical_tx, optical_rx, RAW_tx, RAW_rx;
char temp[10], vccc[10], txbi[10], optx[10], oprx[10], rwtx[30], rwrx[30];
int i;
//Open (or create) the csv file and write the heading row
focat=fopen("fcatdata.csv", "w");

if(focat == NULL)
{
printf("error openining filen");
exit(1);
}
fprintf(focat,"Temp, Vcc, Tx_Bias, Tx, Rx, RAWTx, RAWRxn");
fclose(focat);
focat=fopen("fcatdata.csv", "a+");
i=0;
//start infinite loop
for(;;) 
{
if(!read_eeprom(0x51));
else exit(EXIT_FAILURE);
i=i+1;
//Taking MSB and LSB data and converting
temperature =  (A51[96]+(float) A51[97]/256);
vcc =                   (float)(A51[98]<<8  | A51[99])  * 0.0001;
tx_bias =               (float)(A51[100]<<8 | A51[101]) * 0.002;
optical_tx = 10 * log10((float)(A51[102]<<8 | A51[103]) * 0.0001);
optical_rx = 10 * log10((float)(A51[104]<<8 | A51[105]) * 0.0001);

RAW_tx =               ((float)(A51[102]<<8 | A51[103]) * 0.0001);
RAW_rx =               ((float)(A51[104]<<8 | A51[105]) * 0.0001);

//Display Diagnostics Monitoring Data in Terminal
printf ("SFP Temperature = %4.4fCn", temperature);
printf ("Vcc, Internal supply = %4.4fVn", vcc);
printf ("TX bias current = %4.4fmAn", tx_bias);
printf ("Tx, Optical Power = %4.4f dBm", optical_tx);
printf (", %6.6f mWn", RAW_tx);
printf ("Rx, Optical Power = %4.4f dBm", optical_rx);
printf (", %6.6f mWn", RAW_rx);
printf ("iteration %d n", i);

//Change the integers into strings for appending to file
sprintf(temp, "%4.4f", temperature);
sprintf(vccc, "%4.4f", vcc);
sprintf(txbi, "%4.4f", tx_bias);
sprintf(optx, "%4.4f", optical_tx);
sprintf(oprx, "%4.4f", optical_rx);
sprintf(rwtx, "%6.6f", RAW_tx);
sprintf(rwrx, "%6.6f", RAW_rx);

//Appends DDM Data into a new row of a csv file
//focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%sn",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
//fclose(focat);
}

fclose(focat);
return 0;
}

当我将代码设置为在进入循环之前打开.csv文件时,我在第 1020 次迭代中收到以下错误:

SFP 温度 = 31.9258C

Vcc, 内部电源 = 3.1374V

TX 偏置电流 = 8.0540mA

发射,光功率 = -1.8006 dBm,0.660600 mW

Rx, 光功率 = -40.0000 dBm, 0.000100 mW

无法打开 I2C 设备:打开的文件过多

当我将注释更改为代码底部时,它如下所示:

//Appends DDM Data into a new row of a csv file
focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%sn",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
fclose(focat);

然后注释掉循环之前打开的文件,随后在第 1021 次循环迭代中出现以下错误:

SFP 温度 = 31.8906C

Vcc, 内部电源 = 3.1372V

TX 偏置电流 = 8.0620mA

发射,光功率 = -1.8006 dBm,0.660600 mW

Rx, 光功率 = -40.0000 dBm, 0.000100 mW

分段错误

我认为这与ulimit - n显示1024的结果有关,但我需要能够连续运行此脚本一周,因此更改 ulimit 并不是该问题的真正解决方案。

我通过制作一个脚本来测试这个理论,该脚本无休止地循环并将整数 i 附加到 csv 文件中,并且远远超过 1021 行数据。这已经困扰了我一个星期了。任何帮助,不胜感激。

欢迎对格式等的批评,我不经常在这里(或任何地方)发布

<小时 />
int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0) 
{
fprintf (stderr, "xio: Can't initialise I2C: %sn",
strerror (errno));
return 1;
}
for(i=0; i <128; i++) 
{
fd1 = wiringPiI2CReadReg8 (xio,i);
if  (address == 0x50) 
{
A50[i] = fd1;
}
else 
{
A51[i] = fd1;
}
if (fd1 <0) 
{
fprintf (stderr, "xio: Can't read i2c address 0x%x: %sn",
address, strerror (errno));
return 1;
}
}
return 0;
}

编辑1:阐明了文件打开和关闭的两种场景

编辑 2:添加了有关read_eeprom中内容的信息

编辑3:通过在read_eeprom末尾添加close(fp);来解决

编辑4:通过在read_eeprom末尾添加close(xio);正确解决 - @JohnH的学分

在此过程中只需调用wiringPiI2CSetup()一次。 一种方法可以通过对xio使用静态变量来实现这一点,以便它在调用之间保留值:

int read_eeprom(unsigned char address)
{
int i, value;
static int xio = -1;
if( xio == -1 ) {
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %sn",
strerror (errno));
return 1;
}
}
for(i=0; i <128; i++) {
value = wiringPiI2CReadReg8 (xio,i);
if( value > 0 ) {
if (address == 0x50)
A50[i] = value;
else 
A51[i] = value;
}
else {
fprintf (stderr, "xio: Can't read i2c address 0x%x: %sn",
address, strerror (errno));
return 1;
}
}
return 0;
}

另一种方法是每次进入路由时调用wiringPiI2CSetup(),然后在每次调用之间关闭它:

int read_eeprom(unsigned char address)
{
int xio, i, value;
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %sn",
strerror (errno));
return 1;
}
for(i=0; i <128; i++) {
value = wiringPiI2CReadReg8 (xio,i);
if( value > 0 ) {
if (address == 0x50)
A50[i] = value;
else 
A51[i] = value;
}
else {
fprintf (stderr, "xio: Can't read i2c address 0x%x: %sn",
address, strerror (errno));
close(xio);
return 1;
}
}
close(xio);
return 0;
}

通过在read_eeprom末尾添加close(fd1);来解决,如下所示:

int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0) 
{
fprintf (stderr, "xio: Can't initialise I2C: %sn",
strerror (errno));
return 1;
}
//loop through addresses and extract data from eeprom
for(i=0; i <128; i++) 
{
fd1 = wiringPiI2CReadReg8 (xio,i);
if  (address == 0x50) 
{
A50[i] = fd1;
}
else 
{
A51[i] = fd1;
}
if (fd1 <0) 
{
fprintf (stderr, "xio: Can't read i2c address 0x%x: %sn",
address, strerror (errno));
return 1;
}
}
//close fd1 to prevent segfault and "too many files open" errors
close(fd1);
return 0;
}

用于识别FD泄漏的@Mat信用

相关内容

  • 没有找到相关文章